3.5 Go语言中将函数作为值使用
在匿名函数中,我们已经见过这种形式,即将匿名函数体整体赋值给某个变量,此时该变量就相当于这个函数,Python中也有类似的表达方式。
通过程序的输出,我们能够观察到:
最后请大家思考,如果匿名函数执行了,程序还能正常运行吗?
答案很显然是不行的,你看看到这样的错误./test_function_values.go:8:3: (func literal)() used as value,这里面有两个问题:
我们尝试修复一下这个问题,我们做了以下修改:
再次运行,有以下显著变化:
既然能赋值给变量,也能在map中使用,在下面的例子中,我们就将函数体赋值给map中的值,我们来分析下面的例子:
对于输出结果,我们有以下结论:
由于函数可以作为值,所以很容易作为参数传给函数。这里来看一个简单的示例:
我们来分析一下上面的代码
怎么样使用Go语言中函数的参数传递与调用
按值传递函数参数,是拷贝参数的实际值到函数的形式参数的方法调用。在这种情况下,参数在函数内变化对参数不会有影响。
默认情况下,Go编程语言使用调用通过值的方法来传递参数。在一般情况下,这意味着,在函数内码不能改变用来调用所述函数的参数。考虑函数swap()的定义如下。
代码如下:
/* function definition to swap the values */
func swap(int x, int y) int {
var temp int
temp = x /* save the value of x */
x = y /* put y into x */
y = temp /* put temp into y */
return temp;
}
现在,让我们通过使实际值作为在以下示例调用函数swap():
代码如下:
package main
import "fmt"
func main() {
/* local variable definition */
var a int = 100
var b int = 200
fmt.Printf("Before swap, value of a : %d\n", a )
fmt.Printf("Before swap, value of b : %d\n", b )
/* calling a function to swap the values */
swap(a, b)
fmt.Printf("After swap, value of a : %d\n", a )
fmt.Printf("After swap, value of b : %d\n", b )
}
func swap(x, y int) int {
var temp int
temp = x /* save the value of x */
x = y /* put y into x */
y = temp /* put temp into y */
return temp;
}
让我们把上面的代码放在一个C文件,编译并执行它,它会产生以下结果:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :100
After swap, value of b :200
这表明,参数值没有被改变,虽然它们已经在函数内部改变。
通过传递函数参数,即是拷贝参数的地址到形式参数的参考方法调用。在函数内部,地址是访问调用中使用的实际参数。这意味着,对参数的更改会影响传递的参数。
要通过引用传递的值,参数的指针被传递给函数就像任何其他的值。所以,相应的,需要声明函数的参数为指针类型如下面的函数swap(),它的交换两个整型变量的值指向它的参数。
代码如下:
/* function definition to swap the values */
func swap(x *int, y *int) {
var temp int
temp = *x /* save the value at address x */
*x = *y /* put y into x */
*y = temp /* put temp into y */
}
现在,让我们调用函数swap()通过引用作为在下面的示例中传递数值:
代码如下:
package main
import "fmt"
func main() {
/* local variable definition */
var a int = 100
var b int= 200
fmt.Printf("Before swap, value of a : %d\n", a )
fmt.Printf("Before swap, value of b : %d\n", b )
/* calling a function to swap the values.
* a indicates pointer to a ie. address of variable a and
* b indicates pointer to b ie. address of variable b.
*/
swap(a, b)
fmt.Printf("After swap, value of a : %d\n", a )
fmt.Printf("After swap, value of b : %d\n", b )
}
func swap(x *int, y *int) {
var temp int
temp = *x /* save the value at address x */
*x = *y /* put y into x */
*y = temp /* put temp into y */
}
让我们把上面的代码放在一个C文件,编译并执行它,它会产生以下结果:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :200
After swap, value of b :100
这表明变化的功能以及不同于通过值调用的外部体现的改变不能反映函数之外。
golang-101-hacks(12)——切片作为函数参数传递
注:本文是对 golang-101-hacks 中文翻译。
在Go语言中,函数参数是值传递。使用slice作为函数参数时,函数获取到的是slice的副本:一个指针,指向底层数组的起始地址,同时带有slice的长度和容量。既然各位熟知数据存储的内存的地址,现在可以对切片数据进行修改。让我们看看下面的例子:
In Go, the function parameters are passed by value. With respect to use slice as a function argument, that means the function will get the copies of the slice: a pointer which points to the starting address of the underlying array, accompanied by the length and capacity of the slice. Oh boy! Since you know the address of the memory which is used to store the data, you can tweak the slice now. Let's see the following example:
运行结果如下
由此可见,执行modifyValue函数,切片s的元素发生了变化。尽管modifyValue函数只是操作slice的副本,但是任然改变了切片的数据元素,看另一个例子:
You can see, after running modifyValue function, the content of slice s is changed. Although the modifyValue function just gets a copy of the memory address of slice's underlying array, it is enough!
See another example:
The result is like this:
而这一次,addValue函数并没有修改main函数中的切片s的元素。这是因为它只是操作切片s的副本,而不是切片s本身。所以如果真的想让函数改变切片的内容,可以传递切片的地址:
This time, the addValue function doesn't take effect on the s slice in main function. That's because it just manipulate the copy of the s, not the "real" s.
So if you really want the function to change the content of a slice, you can pass the address of the slice:
运行结果如下