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

go指针的一个小坑

时间:2015-09-15 12:49:10      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

几乎可以肯定的说,go语言中除了闭包在引用外部变量的时候是传引用的,其他的时候都是传值的。如果你说形参可以定义为指针。好吧,那么告诉你这个指针的值其实是按照传值的方式使用的。

下面看个很浅显的例子:

func stillTest(v int) {
    v = v + 100
}
i := 100
fmt.Println("i ", i)
stillTest(i)
fmt.Println("after i ", i)

输出:

i  100
after i  100

两个值是不会有什么区别的。但是指针就会有什么区别么?

func anotherStillTest(v *int) {
    *v = *v + 100
}
fmt.Println("i ", i)
anotherStillTest(&i)
fmt.Println("after i ", i)

输出:

i  100
after i  200

你看到i的值改了,你大喊这难道不是传的引用吗。man,仔细看看下面的例子。

func addressStillTest(v *int) {
    x := 456
    v = &x
}
x := 1000
fmt.Println("x ", x)
addressStillTest(&x)
fmt.Println("after x ", x)

输出:

x  1000
after x  1000

是的,第一个方法中传了一个地址进去,但是我们明显不是对地址做的任何修改操作,而是做了一个dereference操作。然后修改了变量的值。而在上面的这个例子中才是对地址的操作。我们在函数addressStillTest中试图修改x指向的地址,由于x的地址是传值操作的,也就是拷贝过来的,所以修改是无效的。最后的输出结果也说明了这一点。

所以在函数操作方面,任何的参数都是按照传值操作的方式执行的。不管是穿的指针还是一般的一个值都是传值使用的。

下面再看看这个结构体的例子。首先需要有这个:

type Dog struct {
    Name string
    Type string
}
func addressTest(d *Dog) {
    a := &Dog{"another cute dog", "another type"}
    d = a 
}

输出:

Dog  5 6
Another Dog  5 6

对结构体直接做更换地址的操作还是不起作用。再一次表面函数的指针也是传值操作的。

如果要修改一个结构体呢?

func anotherTest(d *Dog) {
    a := &Dog{"another cute dog", "another type"}
    d.Name = a.Name
    d.Type = a.Type
}

输出:

Dog  cute dog ...
Another Dog  another cute dog another type

 

最后说明一个问题。在c,c++里如果从函数内部返回一个局部变量的指针的话是不对的。但是在Go里是可以的。Go的编译器会检查函数的局部变量指针是否会作为返回值给外部使用,如果是的话则将这个变量放在heap上延长其生命周期。

func test() *Dog {
    return &Dog{"cute dog", "..."}
}
d := test()
fmt.Println("Dog ", d.Name, d.Type)

输出:

Dog  cute dog ...

 

坑已填平!

 

go指针的一个小坑

标签:

原文地址:http://www.cnblogs.com/sunshine-anycall/p/4809853.html

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