函数可以赋值给变量,不能给一个变量赋不同签名的函数。
函数值是可以比较的,不同变量指向相同的函数或者nil的话就是相同的,
指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递
函数也是可以以函数为参数来传递的
call(1,Add(1,2))
func Add(a,b int){
return a+b
}
func call(y int, f func(int,int)){
f(y,2)
}
函数在声明的时候也是可以进行为返回值命名的
func a()(a int){}进行命名的话就必须要加上括号,有命名也不一定一定要使用。
使_可以匹配不需要的值然后丢弃
使...type可以声明一个变长参数
func cu(a int,b ...int){}这个变长参数必须是函数参数中的最后一个,不能放在其他函数的前面。
使用变长参数是go隐性创建了一个切片,后面通过切边的方式使用这些参数
package main
import "fmt"
func main() {
var b = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Print(sum(0, b[:]...))
}
func sum(a int, b ...int) int {
for i := range b {
a += i
}
return a
}
传递a的值之后,就可以传递任意数量的值作为b的值,b的类型为[]int
使defer可以在函数return之后再执行,可以再任意位置写这个语句或者调用函数
func function1() {
fmt.Printf("In function1 at the top\n")
defer function2()
fmt.Printf("In function1 at the bottom!\n")
}可以用于最后的资源释放或者返回值的处理,也可以进行日志打印函数追踪
如果同时写多个个defer的话,会以逆序的方式执行
匿名函数,可以在函数体中定义,不能够独立的存在,只能赋值给其他变量或者直接调用。
func() {
sum := 0
for i := 1; i <= 1e6; i++ {
sum += i
}
}()//这个表示要调用当返回值是一个匿名函数时,使用变量接收函数时,函数会执行,但是函数返回的函数不会执行,只有在再次调用的时候才会运行,
不调用的匿名函数中使用了x,所以会一直指向x,x不会释放,如果使用变量引用Adder()z:=Adder()z每次被调用都是返回的匿名的函数,匿名函数,因为x不会被释放,所以每次调用都是上一次计算过的结果。使用新的变量接收同一含数a:=Adder()a不会使用相同的x
如果想要长时间使用一个算法得到的不同变量,直接返回匿名函数,同一个接收匿名函数的变量匿名函数计算的值是累计的,函数中指向的变量是不会被释放的,但是更换接收变量就会重置
func Adder() func(int) int {
var x int
return func(delta int) int {
x += delta
return x
}
}如果想要手动重置可以直接讲接收函数变量值设为nil,或者使用{}
func main() {
{
a:=sum(0, b[:]...)
}//在这里a会被释放
}
func sum()func (){
return func(){}
}因为{}是一个独立的代码块,但是defer是在函数结束时才会指向,而不是代码块结束,所有在独立区域执行需要匿名函数
MakeAddSuffix这个样的返回值是另一个函数的函数被称为工厂函数
func MakeAddSuffix(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}