码迷,mamicode.com
首页 > 其他好文 > 详细

go系列之值传递、引用传递与指针传递

时间:2018-05-10 15:34:08      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:字典   解决   make   结构   https   共享资源   变量   .com   初始化   

 

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系列之值传递、引用传递与指针传递

标签:字典   解决   make   结构   https   共享资源   变量   .com   初始化   

原文地址:https://www.cnblogs.com/mazhimazhi/p/9019420.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!