为什么struct I pass不会改变

时间:2015-12-28 11:20:30

标签: function pointers go

我通过引用将结构传递给函数。

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

但它没有发生。

任何人都可以解释原因吗?

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

3 个答案:

答案 0 :(得分:1)

您不是在更改函数内部的结构,而是通过将其设置为不同的内存地址来更改该值。换句话说,您没有更改t引用的地址中存储的对象,您正在更改t本身的指针值,这不会更改指针值函数外的t变量(因为Golang是按值传递的)。

为了做你想做的事,代码应该与你为intbyRef做的类似,即:

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

然而,这会因为nil-pointer dereference而引起恐慌。你的主要功能也应该用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)
}

此外,您可能希望防范nil值并返回错误,尤其是对于包内部的函数。

答案 1 :(得分:0)

在我们的代码中,您在函数更改中创建ttt的新对象并将其赋值给t,该函数作为参数传递给函数。在go中,参数是按值传递的,因此在函数更改结束时,将值赋值给t仅适用于函数的范围。为了将更改传播到调用函数返回值,并将其更改回来。

对代码进行了更改,请查看播放地点链接 https://play.golang.org/p/S3GK0JLDHn

答案 2 :(得分:0)

您正在将已初始化指针值传递给intByRef并更改已取消引用的值。

change中,您传递的不是初始化的指针值(也就是nil)并为其分配另一个指针。

所以你做了两件事。

您应该知道,当您将指针传递给函数时,您会传递该指针的副本(指向相同的值)。这就是为什么main t在将其传递给change后未发生变化的原因。它指向" old"记忆地址。

如果要更改传递给函数的ttt指针的值,可以像intByRef中那样执行,但指针必须初始化(又名。分配)。否则你会尝试取消引用nil。

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)
}