2015-12-28 27 views
-1

我通过引用将一个结构传递给一个函数。为什么我通过的结构不变

我期待着如果我定义和更改函数内部的结构,我可以在外面获得新的值。

但它没有发生。

任何人都可以解释为什么吗?

package main 

import "fmt" 

func intbyRef(i *int) { 
    *i = 10 
} 

type ttt struct { 
    a int 
} 

func change(t *ttt) { 
    var p ttt = ttt{7} 
    fmt.Println(p) 
    t = &p 

} 

func main() { 

    i := 1 
    var t *ttt 

    fmt.Println(i) 
    fmt.Println(t) 

    change(t) 
    intbyRef(&i) 

    fmt.Println(i) 
    fmt.Println(t) 
} 

您可以尝试在这里的代码:https://play.golang.org/p/I-GIdIZ9c6

+1

请考虑忘却这个 “参照” 名不副实。在某些语言中,有*的区别:例如,在Python和PHP中,整数类型的值通过值传递,类类型的对象通过引用传递。相比之下,在Go中,所有值都通过值传递,只要您可以显式传递指向值的指针即可,如果您希望被调用者修改指向的值,或者希望避免复制开销。 – kostix

+1

考虑阅读[this](http://stackoverflow.com/a/25354231/720999)和[this](http://stackoverflow.com/a/23551970/720999)。 – kostix

回答

0

在我们的代码,你正在创建功能变化TTT的新对象,并为其分配到t其作为参数传递给函数。在go中,参数是按值传递的,所以当函数改变结束时,你赋值给t只是函数的作用域。为了将更改传播到调用函数返回值并将其分配回去。

所做的更改您的代码,请打地面连杆 https://play.golang.org/p/S3GK0JLDHn

+0

谢谢,现在我明白了,所有的偶数指针都是作为价值传递的。 –

1

你不改变函数内部的结构,你将其设置为不同的内存地址更改值。换句话说,你并没有改变存储在t引用的地址上的对象,你改变的指针值为t本身,它不会改变函数外的t变量的指针值(因为Golang通过值)。

为了做到你想要什么,代码应该类似于你在做什么intbyRef,即:

func change(t *ttt) { 
    var p ttt = ttt{7} 
    fmt.Println(p) 
    *t = p 
} 

然而,这将与未缴指针引用恐慌。你的主要功能也应该做到你用INT做什么:

func main() { 

    i := 1 
    // var t *ttt 
    t := new(ttt) 

    ... 
} 

下面的完整代码(操场链接here):

package main 

import "fmt" 

func intbyRef(i *int) { 
    *i = 10 
} 

type ttt struct { 
    a int 
} 

func change(t *ttt) { 
    var p ttt = ttt{7} 
    fmt.Println(p) 
    // t = &p 
    *t = p 

} 

func main() { 

    i := 1 
    // var t *ttt 
    t := new(ttt) 

    fmt.Println(i) 
    fmt.Println(t) 

    change(t) 
    intbyRef(&i) 

    fmt.Println(i) 
    fmt.Println(t) 
} 

此外,您可能想在防范零值和返回错误,特别是对于你的包内部的函数。

+1

关于«一般来说,你应该防范零值和返回错误» - 请不要! [Here's](http://stackoverflow.com/a/22865084/720999)为什么。 – kostix

0

您正在通过初始化指针值为intByRef并更改取消引用的值。

change您传递未初始化的指针值(又名nil)并为其分配另一个指针。

所以你正在做两件不同的事情。

您应该知道,当您将指针传递给函数时,会传递该指针的副本(指向相同的值)。这就是为什么maint在传递到change后没有改变。它指向“旧”内存地址。

如果你想改变ttt指针传递给像你在intByRef做到这一点,你可以做到这一点的函数的值,但指针必须进行初始化(亦称分配)。否则,你会尝试解除零引用。

playground

func change(t *ttt) { 
    var p ttt = ttt{7} 
    fmt.Println(p) 
    *t = p 
} 

func main() { 
    t := new(ttt) 
    fmt.Println(t) 
    change(t) 
    fmt.Println(t) 
} 
相关问题