go系列之值傳遞、引用傳遞與指針傳遞
阿新 • • 發佈:2018-05-10
參考 lse make mod s/4 object 引用類型 obj 值傳遞
1、關於值傳遞、引用傳遞與指針傳遞
當一個變量或者新值被創建時, 如果沒有為其明確指定初始值,go語言會自動初始化其值為此類型對應的零值, 各類型零值如下:
false : bool, 0: integer 0.0: float "": string nil : pointer, function, interface, slice, channel, map
對於復合類型, go語言會自動遞歸地將每一個元素初始化為其類型對應的零值。比如:數組, 結構體。
nil 是專門為go語言的指針類型和引用類型準備的,go語言的數組和結構體可是值類型, 切片、字典或通道為引用類型。所以如果數組作為函數參數時,因為是值類型, 所以要復制 。
在go語言中沒有引用傳遞,只有值傳遞。
例1:值傳遞
func main() { a := []string{"a", "b"} test(a) fmt.Println(a) } func test(b []string) { b = []string{"cc", "cc"} }
打印出來後值為:[a b],表明在傳遞時是復制了一份單獨的數組結構。
指針傳遞也是值傳遞。
例2:指針傳遞,也是值傳遞
func main() { a := &[]string{"a", "b"} test(a) fmt.Println(*a) } func test(b *[]string) { b = nil }
打印出來後為:[a b]。傳遞指針時,能修改指針所指向的值,並不能修改指針本身的值。
傳引用
var a Object modify(a) // 修改a的值 print(a)
如果函數modify
修改a
的值, 然後print
打印出來的也是修改後的值,那麽就可以認為modify是通過引用的方式使用了參數a。而如上例子證明了指明傳遞是值傳遞。
例3:引用傳遞
func main() { a := new(int) fmt.Println(a) func() { a = nil }() fmt.Println(a) }
打印結果為:
0xc042008220
<nil>
關於指針傳遞與引用傳遞參考:https://studygolang.com/articles/4810
2、關於go中的map
go語言中的map不是協程安全的,如果要多個協程對同 一個map進行寫操作,則會出錯:
fatal error: concurrent map writes
舉例:
func main() { Map := make(map[int]int) for i := 0; i < 100000; i++ { go writeMap(Map, i, i) go readMap(Map, i) } } func readMap(Map map[int]int, key int) int { return Map[key] } func writeMap(Map map[int]int, key int, value int) { Map[key] = value }
因為map為引用類型,所以即使函數傳值調用,參數副本依然指向映射m, 所以N個goroutine並發寫同一個映射m,共享資源會遭到破壞。
解決辦法就是加鎖,或者channel排隊串行化。
go系列之值傳遞、引用傳遞與指針傳遞