值类型和引用类型的误区

  Go语言没有引用类型,可以查看Go语言创始人Robert Griesemer的提交(2013-04-03):
 
  https://github.com/golang/go/commit/b34f0551387fcf043d65cd7d96a0214956578f94
 
 
 
  所有的函数入参都是值传递(即值拷贝),没有什么所谓的引用传递。map、chan、切片(slice)等类型的变量入参,从结果来看似乎是引用传递,但本质原因是这些类型的数据结构设置了一个字段来保存指针,在函数体内更改数据都是通过指针来进行的。
 
  查看切片(slice)源码文件“{Go安装目录}/src/runtime/slice.go”就可以看到切片的数据结构有一个字段保存指向数组的指针。
 
  所以Go语言没有值类型和引用类型的区分,如果非要区分应该是数据结构是否有指针字段。
 
  无指针:基本数据类型(int、float、bool、string)、数组、结构体(struct)
 
  有指针:map、chan、切片(slice)、接口(interface)、函数(func)、指针
 
  无指针的数据类型变量通常分配在栈内存,栈内存在函数调用完后会被释放;有指针的数据类型变量通常分配在堆内存,并通过GC(Garbage Collection)回收。



  通过下面的代码可以直观地看到,切片变量入参实际上传入的是指针。

package main

import "fmt"

func Test(n []string) {
   n[0] = "天皇·" + n[0]
   n[1] = "地皇·" + n[1]
   n[2] = "人皇·" + n[2]
}

func main() {
   name := []string{"燧人", "神农", "伏羲"}
   Test(name)
   fmt.Println(name) // [天皇·燧人 地皇·神农 人皇·伏羲]
}

Copyright © 2024 码农人生. All Rights Reserved