从零开始学Go之函数(一):匿名函数与闭包

匿名函数:

匿名函数类似于函数声明,但是没有函数名

func (函数参数列表) (函数返回值列表){

函数内部代码

}

在函数声明后可以加入参数直接调用

func main() {
 g := func(a int) uint { //匿名函数
  return uint(a + 14)
 }(10) //声明后调用
 f := func(a int) uint { //匿名函数
  return uint(a + 14)
 }
 re := f(100)
 fmt.Println(g, re)
}

运行结果

24 114

 

闭包:

闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)

简单的看就是匿名函数作为返回值

拿个网上的例子:

参考:https://www.cnblogs.com/ralap7/p/9195677.html

func squares() func() int {
 var x int
 return func() int {
  x++
  return x * x
 }
}
​
func main() {
 f1 := squares()
 f2 := squares()
​
 fmt.Println("first call f1:", f1())
 fmt.Println("second call f1:", f1())
 fmt.Println("first call f2:", f2())
 fmt.Println("second call f2:", f2())
}

运行结果:

first call f1: 1

second call f1: 4

first call f2: 1

second call f2: 4

在这里函数就是squares,引用环境就是squares内部,虽然f1,f2都是x的平方,但是他们的环境不同所以两次运行结果都是相同的。

一开始用着C的思维一直想不懂闭包,函数里的变量不是分配到栈中用完就释放了吗,到后面学到了变量逃逸机制后才开始理解因为Go会自动分析语句识别出作用域,因为外部有对x的引用,所以变量x逃逸到了堆中保存而不是在栈中,所以这种写法是可以的。

go build --gcflags=-m main.go 命令可以看到变量逃逸到堆上而不是栈上,所以变量被保存在函数环境中。

 

函数可变参数:

参数类型:...interface{}

func test1 (a ...interface{})
func test2 (a int, b ...interface{})//可变参数需要放在不可变参数后

当不可变参数和可变参数同时出现在函数参数中时,可变参数需要放在不可变参数后

通过类型断言和range取出可以取出值

func printTypeValue(slist ...interface{}) string {
 for _, s := range slist {
   // 将interface{}类型格式化为字符串
   str := fmt.Sprintf("%v", s)
   // 类型的字符串描述
   var typeString string
   // 对s进行类型断言
   switch s.(type) {
   case bool: // 当s为布尔类型时
     typeString = "bool"
   case string: // 当s为字符串类型时
     typeString = "string"
   case int: // 当s为整型类型时
     typeString = "int"
   }
 }
 return typeString
}
posted @ 2019-07-02 00:08  VingB2by  阅读(166)  评论(0编辑  收藏  举报