Golang函数

Posted by 淦 Blog on January 24, 2023

使用方式

函数是一等公民(first-class) ,可将它看作变量,并且可作为参数传递、返回及赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
//函数作为返回值
func makeGreeter() func() string {
   return func() string {
      return "hello jonson"
   }
}

//函数作为参数
func visit (numbers []int, callback func(int)) {
   for _, n :=range numbers {
      callback(n)
   }
}

闭包与陷阱

Go语言同样支持匿名函数和闭包。闭包(Closure)是在函数作为一类公民的编程语言中实现词法绑定的一种技术,闭包包含了函数的入口地址和其关联的环境。闭包和普通函数最大的区别在于,闭包函数中可以引用闭包外的变量。

当闭包与range同时使用时,最终协程会打印出values切片的最后一个值。因为当前val值引用的是同个地址的数据, 所以在range 循环的过程中,会不断在 val地址中更 新数据。而在闭包中,由于引用了外部变量val,所以在访问时会获取val 地址中的值,可能会获取最后放入其中的值,而不是遍历所有值,从而导致严重的错误。

1
2
3
4
5
for _, val := range values {
    go func() {
        fmt.Println(val)
    }()
}

修复该问题的办法是通过函数传递参数,从而避免闭包引用导致的陷阱。

1
2
3
4
5
for _, val := range values {
    go func(val string) {
        fmt.Println(val)
    }(val)
}