go:using pointer允许更改结构的内容。为什么?

时间:2012-08-05 18:37:59

标签: pointers go

考虑以下示例。我不完全理解“在后台”会发生什么并寻求解释。当我从main函数调用Foo时,这个版本似乎会复制struct AddToEntry。对?我怎样才能在代码中“证明”这个?

当go制作结构的副本时,我只是操纵结构的副本,当我回到main函数时,我会看到原来的那个?

当我期待一个指针(参见代码中的注释)时,一切都很好,我的结构不会被复制。怎么能避免这种“错误”?我怎样才能确保我没有复制结构?是否有可能的编译时间/运行时间检查,或者我是否小心?

package main

import (
    "fmt"
)

type Foo struct {
    Entry []string
}

func MakeFoo() Foo {
    a:=Foo{}
    a.Entry = append(a.Entry,"first")
    return a
}

// if I change (f Foo) to (f *Foo), I get 
// the "desired" result
func (f Foo) AddToEntry() {
    f.Entry = append(f.Entry,"second")
}


func main() {
    f:=MakeFoo()
    fmt.Println(f) // {[first]}
    f.AddToEntry()
    fmt.Println(f) // {[first]}
}

3 个答案:

答案 0 :(得分:8)

您的方法签名为func (f Foo) AddToEntry()。方法的工作方式f.AddToEntry()与:

相同
g := Foo.AddToEntry
g(f)

接收器只是另一个参数。为什么这很重要?传递结构并在函数中修改它会发生什么?在C,Go和其他值传递语言中,参数中给出的结构只是一个副本。因此,您无法修改原始内容。只返回新结构。

定义func (f *Foo) AddToEntry()时,您将接收器(第一个参数)定义为指针。显然,给定一个指针,您可以修改原始结构。隐藏的是您在Go中访问结构时隐式引用。换句话说,(*ptrFoo).Entry与Go中的ptrFoo.Entry相同。

所以这里的问题是,对于那些不习惯的人来说,语法隐藏了一些正在发生的事情。在C中,除非传递指向它的指针,否则永远不能编辑结构。 Go中也是如此。您需要使用指针接收器来修改您接收的内容。

答案 1 :(得分:5)

答案 2 :(得分:2)

  

如何确保我不复制结构?有可能吗?   编译时间/运行时检查,或者我是否小心?

这里简短的回答是没有,你不能做编译时或运行时(1)检查 为此 - 你必须要小心。一旦你对go有点熟悉,这就变得很自然了。

(1) 从技术上讲,你的函数可以使用type switch查询类型是否为指针,但如果你记得这样做,你也会记得将参数作为指针。 < / p>