值傳遞
值傳遞的資料型別
基本型別
基本型別是Go語言自帶的型別,比如數值型別、浮點型別、字元型別以及布林型別,他們本質上是原始型別,也就是不可改變的,所以對他們進行操作,一般都會返回一個新建立的值,所以把這些值傳遞給函式時,其實傳遞的是一個值的副本。
func changeDate(name string) string{
name = name+"你的資料被改變了"
return name
}
func main() {
name:="董雷"
tmpName := changeDate(name)
fmt.Println(name)
fmt.Println(tmpName)
}
//返回結果
董雷
董雷你的資料被改變了
上面的案例name在changeDate方法中修改了值,但是並沒有影響main中的name,也就是說,我們傳遞的時一個副本,並且返回一個新建立的字串。
基本型別因為是拷貝的值,並且在對他進行操作的時候,生成的也是新建立的值(寫時複製機制),所以這些型別在多執行緒裡是安全的,我們不用擔心一個執行緒的修改影響了另外一個執行緒的資料。
引用傳遞
引用型別和原始的基本型別恰恰相反,它的修改可以影響到任何引用到它的變數
引用型別有
- 切片、[]string
- map、mapp[string]string
- 介面、interface{}
- 函式型別、
- 管道(chan)
引用型別之所以可以引用,是因為我們建立引用型別的變數,其實是一個標頭值,標頭值裡包含一個指標,指向底層的資料結構,當我們在函式中傳遞引用型別時,其實傳遞的是這個標頭值的副本,它所指向的底層結構並沒有被複制傳遞,這也是引用型別傳遞高效的原因。
案例
func changeDate(slice []string) []string {
slice[0] = "你的企片被改了"
return slice
}
func main() {
slice := []string{"我是切片"}
tmpSlice := changeDate(slice)
fmt.Println(slice)
fmt.Println(tmpSlice)
}
//返回結果
[你的企片被改了]
[你的企片被改了]
可以看到切片在函式裡面修改了,main裡面的變數也會一起被修改,所以是引用傳遞
結構型別
結構體是值傳遞,會複製一個新值,包括下面的子元素不管是什麼型別都會被影響
如何實現引用傳遞 &結構體 這種方式
程式碼
type person struct {
age int
name []string
point *map[string]string
}
func modify(p person) {
p.age =p.age+10
p.name = []string{"王子"}
p.point = &map[string]string{"name":"李四"}
}
func main() {
tmpMap := make(map[string]string)
tmpMap["name"] = "站桑"
donglei := person{10,[]string{"董雷"},&tmpMap}
fmt.Println(donglei)
modify(donglei)
fmt.Println(donglei)
}
//返回結果
{10 董雷}
{10 董雷}
自定義型別
自定義型別的好處,最主要的就是就是可以對自定義型別新增方法
本作品採用《CC 協議》,轉載必須註明作者和本文連結