前进:使用指针可以更改结构的内容。为什么?

考虑以下示例。我不完全了解“后台”会发生什么,并寻求解释。从主函数Foo调用时,此版本似乎复制了该结构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]}

}


DIEA
浏览 241回答 2
2回答

青春有我

您的方法签名为func (f Foo) AddToEntry()。方法的工作方式与以下方式f.AddToEntry()相同:g := Foo.AddToEntry g(f)接收器只是另一个参数。为什么这很重要?当您传递结构并在函数中对其进行修改时会发生什么?在C,Go和其他按值传递语言中,参数中给出的结构仅是副本。因此,您不能修改原始文件。只返回新的结构。定义时func (f *Foo) AddToEntry(),您正在将接收器(第一个参数)定义为指针。显然,给定一个指针,您可以修改原始结构。隐藏的是您在Go中访问结构时隐式引用。换句话说,(*ptrFoo).Entry与ptrFoo.EntryGo中的相同。因此,这里的问题是,对于那些不习惯的人,语法隐藏了一些正在发生的事情。在C语言中,除非传递了指向结构的指针,否则您将永远无法编辑该结构。Go中也会发生同样的情况。您需要使用指针接收器才能修改接收的内容。

繁星点点滴滴

如何确定不复制该结构?是否有可能对此进行编译时/运行时检查,或者我要小心吗?简短的答案是,不,您不能为此进行编译时或运行时(1)检查-您只需要小心。一旦您对go有了一些熟悉,这便成为自然。(1) 从技术上讲,您的函数可以使用类型开关查询类型是否为指针,但是如果您记得这样做,则还记得将参数设置为指针。

交互式爱情

您阅读过此Go文档吗?我应该在值或指针上定义方法吗?方法:指针与值Go编程语言规范
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go