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

top*_*kip 2 pointers go

请考虑以下示例.我不完全理解"在后台"会发生什么并寻求解释.Foo当我AddToEntry从main函数调用时,这个版本似乎制作了struct的副本.对?我如何在代码中"证明"这一点?

当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]}
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*erg 8

你的方法签名是func (f Foo) AddToEntry().方法的工作方式f.AddToEntry()与以下相同:

g := Foo.AddToEntry
g(f)
Run Code Online (Sandbox Code Playgroud)

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

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

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