1.值类型和引用类型
package main
import (
"fmt"
)
func add(num int) {
num += 1
}
func addArry(arry [3]int){
arry[0] = 10
}
func addSlice(slice []int){
slice[0] = 10
}
func addMap(m map[int]int){
for k,v := range m{
v += 1
m[k] = v
}
}
func main() {
num := 10 //值类型
add(num)
fmt.Println("num after",num)
arry := [3]int{8, 7, 6} //值类型
fmt.Println("arry before", arry)
addArry(arry)
fmt.Println("arry after", arry)
slice := []int{8, 7, 6} //引用类型
fmt.Println("slice before", slice)
addSlice(slice)
fmt.Println("slice after", slice)
m := make(map[int]int) //引用类型
m[1] = 1
fmt.Println("map before", m)
addMap(m)
fmt.Println("map after", m)
}
运行后的结果是:
num after 10
arry before [8 7 6]
arry after [8 7 6]
slice before [8 7 6]
slice after [10 7 6]
map before map[1:1]
map after map[1:2]
可以看到单个值和数组都是属于值类型,在函数内部修改值但是外部并不会改变,而切片和字典属于引用类型,在函数内部修改值,外部的值随之改变。
值类型:
变量直接存储,内存通常在栈中分配。
基本数据类型int、float、bool、string以及数组和struct。
引用类型:
变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配。通过GC回收。
slice、map、chan等都是引用类型
也就是值类型赋值或者函数传参过后,进行了拷贝操作,已经是两个指向不同内存地址的变量,而引用类型,赋值或者函数传参过后,指向的还是同一个内存地址,所以引用类型在函数内层修改值过后,外层变量上的值也会随之改变。
由于结构体是值类型,所以在对存储了大量数据的结构体进行函数传参时最好使用指针传参。
如果直接使用结构体那么会进行大量数据的内存拷贝,导致内存资源浪费。