函数
函数为什么是一等公民呢?和其他主流语言不同,在go里面函数的地位是不一样的。
与其他主要编程语⾔的差异
- 可以有多个返回值
 - 所有参数都是值传递:slice,map,channel 会有传引⽤的错觉(在传递过去的时候,传入到函数当中,在函数里面修改参数的值,外面也可以感受到,难道这不是传引用吗?😳😳😳😳😳😳😳😳😳其实这是一个错觉,就比如slice,切片背后实际上对应的是数组,切片本身是一个数据结构,数据结构里面包含指向数组到指针,即便是在传值的情况下,结构被复制到函数里面了,通过指向数组到指针去操作具体值到时候,其实操作的是同一块空间,所以就会有一种传引用到错觉,实际上是结构被复制了,包含的指针指向到是同一个后端到数组,所以才有这个错觉。)
 - 函数可以作为变量的值
 - 函数可以作为参数和返回值
 
传递参数类型 值类型 引用类型
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]
}看下图理解最方便:😂😂😂😂😂










