go系列之值传递引用传递与指针传递
Posted mazhimazhi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go系列之值传递引用传递与指针传递相关的知识,希望对你有一定的参考价值。
1、关于值传递、引用传递与指针传递
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系列之值传递引用传递与指针传递的主要内容,如果未能解决你的问题,请参考以下文章