返回值及参数说明闭包
func A(a int, b string) (int, string, int) { //第一个小括号当中是你的参数列表,第二个小括号是你的返回值列表 }
func A(a, b, c int) (int, string, int) { //若是abc都是int型的话,能够按照这种方法进行简写,一样的方法也适用于返回值当中 }
func A() (a, b, c int) { //1:若是这样写的话就必需要命名返回值 //命名返回值和不命名返回值得区别 }
func A() (int, int, int) { // //命名返回值和不命名返回值得区别 a, b, c := 1,2,3 return a,b,c //若是此时没有命名返回值的时候,那么在返回值得时候就必须写上return a,b,c //固然为了代码的可读性,这里咱们规定必须return 的时候加上返回值名 }
不定长变参函数
package main import "fmt" func main() { A(1,2,3,4,5,6,7) } func A(a ...int) { // 这里采用的是不定长变参,不定长变参必须是参数的最后一个参数,后面不能再跟 b string这样的参数 fmt.Println(a) }
package main import "fmt" func main() { s1:= []int{1,2,3,4} a,b :=1,2 A(a,b) fmt.Println(a,b) B(s1) fmt.Println(s1) } func A(a ...int) { //这里传进来的其实是一个slice,引用类型 a[0] = 3 a[1] = 4 //尽管咱们在函数A当中接收到的是一个slice,可是它获得的是一个值拷贝 //和直接传递一个slice的区别看函数B fmt.Println(a) } func B(s []int) { //这里并非传递一个指针进去,而是对这个slice的内存地址进行了一个拷贝 //这里还能够看到像int型、string型进行常规的参数传进去的话,只是进行了个值拷贝,slice传进去虽然也是拷贝,可是它是内存地址的拷贝 s[0] = 4 s[1] = 5 s[2] = 6 s[3] = 7 fmt.Println(s) //在这里 咱们看到咱们在函数B当中的修改,实际上影响到了咱们main函数当中的变量s1 //若是直接传递一个slice,它的修改就会影响到这个slice的自己 } PS:值类型和引用类型进行函数传参拷贝是不同的,一个是拷贝值,一个是拷贝地址
package main import ( "fmt" ) func main() { a := 1 A(&a) //这里取出a的地址 fmt.Println(a) } func A(a *int) { //传递的是指针类型 *a = 2 //在操做的时候须要去它的值进行操做,这个时候函数A就能够改变原始a的值 fmt.Println(*a) }
函数类型的使用指针
package main import ( "fmt" ) func main() { a := A a() //这个时候是将A的函数类型赋值给a,在go语言当中一切皆是类型啊 } func A() { fmt.Println("Func A") }
匿名函数的使用code
package main import ( "fmt" ) func main() { a := func() { //此时这个代码块就是一个匿名函数,这个函数自己没有名称,咱们将她赋值给a,而后调用 fmt.Println("Func A") } a() //依然能够打印func A }
GO语言当中的闭包内存
package main import ( "fmt" ) func main() { f := closure(10) res1 := f(1) fmt.Println(res1) res2 := f(2) fmt.Println(res2) } func closure(x int) func(int) int { fmt.Printf("%p \n", &x) return func(y int) int { fmt.Printf("%p \n", &x) return x + y } } //这里能够看出3次打印x的地址都是同样的
若是函数体内某个变量做为defer时匿名函数的参数,则在定义defer时即已经得到了拷贝,不然则是引用某个变量的地址资源
Panic能够在任何地方引起,但recover只有在defer调用的函数中有效原型
package main import ( "fmt" ) func main() { fmt.Println("A") defer fmt.Println("B") defer fmt.Println("C") } //PS:打印的结果就是A C B
package main import ( "fmt" ) func main() { for i := 0; i < 3; i++ { //defer fmt.Println(i) defer func() { fmt.Println(i) }() //调用这个函数 } } //刚才直接打印的时候,是做为一个参数传递进去,运行到defer的时候是将这个i的值进行了一个拷贝,因此打印的是 2 1 0 //这种状况下i一直是一个地址的引用,i一直引用的是局部变量的i,在退出这个循环体的时候 i已经变成了3,在main函数return的时候,开始执行defer语句,defer语句的时候i已经变成了3
异常机制string
package main import ( "fmt" ) func main() { A() B() C() } func A() { fmt.Println("Func A") } func B() { defer func() { if err := recover(); err != nil { fmt.Println("Recover in B") } }() panic("Panic in B") } func C() { fmt.Println("Func C") }
package main import ( "fmt" ) func main() { var fs = [4]func(){} for i := 0; i < 4; i++ { defer fmt.Println("defer i=", i) //这个i是传递进来的参数,因此是值得拷贝 defer func() { fmt.Println("defer_closure i=", i) //这里的i是引用外部的i,因此循环结束后,i变成了4 }() fs[i] = func() { fmt.Println("closure i = ", i) //这里也是引用外部的i,因此循环结束后i变成了4 } } for _, f := range fs { f() } }