函数


函数为什么是一等公民呢?和其他主流语言不同,在go里面函数的地位是不一样的。

与其他主要编程语⾔的差异

  1. 可以有多个返回值
  2. 所有参数都是值传递:slice,map,channel 会有传引⽤的错觉(在传递过去的时候,传入到函数当中,在函数里面修改参数的值,外面也可以感受到,难道这不是传引用吗?😳😳😳😳😳😳😳😳😳其实这是一个错觉,就比如slice,切片背后实际上对应的是数组,切片本身是一个数据结构,数据结构里面包含指向数组到指针,即便是在传值的情况下,结构被复制到函数里面了,通过指向数组到指针去操作具体值到时候,其实操作的是同一块空间,所以就会有一种传引用到错觉,实际上是结构被复制了,包含的指针指向到是同一个后端到数组,所以才有这个错觉。)
  3. 函数可以作为变量的值
  4. 函数可以作为参数和返回值

 

 

传递参数类型 值类型 引用类型


1) 值传递 值类型--》值拷贝


在 Go 语言中参数传递默认均为值传递(形参为实参变量的副本), 对于引用类型数据因其底


层共享数据结构,所以在函数内可对引用类型数据修改从而影响函数外的原变量信息



2) 引用传递。引用类型的时候--》也是值拷贝,只不过底层有个地址,导致使用的地址空间是一样的,所以在函数内部是可以影响函数外面变量的




所以go语言当中都是值拷贝,也就是值传递,不能说在函数里面是引用传递,其次在值传递的时候


为什么引用类型的参数可以影响函数外表的变量?因为值拷贝的时候底层是有地址和指针的。



可以通过将变量的地址通过指针类型递给函数,此时可通过指针对函数外的原变量进行修改。


先来看看变量的作用域 

func main()  {
name := "jack"
nums := []int{}

fmt.Println(name,nums)

func(){

fmt.Println(name,nums)
name = "lucas"
nums = []int{1,2,3}
fmt.Println(name,nums)
}()

fmt.Println(name,nums)

}

jack []
jack []
lucas [1 2 3]
lucas [1 2 3]



func main() {
name := "jack"
nums := []int{}

fmt.Println(name,nums)

func(){

fmt.Println(name,nums)
name := "lucas"
nums := []int{1,2,3}
fmt.Println(name,nums)
}()

fmt.Println(name,nums)

}

jack []
jack []
lucas [1 2 3]
jack []

值类型的参数和引用类型的参数 

func main()  {
name := "jack"
nums := []int{1,2,3}

fmt.Println(name,nums)

func(pname string,pnums []int){
fmt.Println(pname,pnums) //jack [1 2 3]
pname = "lucas"
pnums = append(pnums,4,5,6) //大于cap了,所以产生了新切片,和原来的没关系了
fmt.Println(pname,pnums) //lucas [1 2 3 4 5 6]

}(name,nums)

fmt.Println(name,nums) //jack [1 2 3]

}

可以看到在append之后会产生新的切片! 😏😏😏😏

   a := []int{1,2,3}
fmt.Printf("%p,%d,%d\n",&a,len(a),cap(a))

b := append(a,4,5,6)
fmt.Printf("%p,%d,%d",&b,len(b),cap(b))

0xc0000a6018,3,3
0xc0000a6030,6,6

上面是pnums = 重新赋值,指向另外一个地方了,所以对原来的切片没有影响,如果是pnums[0] = 100就是对原来的切片进行修改,因为底层有指针,指向的数组是同一个。

func main()  {
name := "jack"
nums := []int{1,2,3}

fmt.Println(name,nums)

func(pname string,pnums []int){
fmt.Println(pname,pnums) //jack [1 2 3]
pname = "lucas"
pnums[0] = 100
fmt.Println(pname,pnums) //lucas [100 2 3]

}(name,nums)

fmt.Println(name,nums) //jack [100 2 3]
}

看下图理解最方便:😂😂😂😂😂

Go 函数 参数值传递_数组