为了账号安全,请及时绑定邮箱和手机立即绑定

为什么我的字段在函数调用后被截断?

为什么我的字段在函数调用后被截断?

Go
手掌心 2021-09-27 18:29:44
http://play.golang.org/p/xFBSZta2CL我已经尝试了 2 个小时。进入主函数,我们立即进入第 24-26 行:prompter.Define(&Field{"name"})prompter.Define(&Field{"age"})定义函数:fmt.Printf("fields: %+v\n", c.fields)c.fields = append(c.fields, f)fmt.Printf("fields: %+v\n", c.fields)函数调用后,c.fields数组又为空了!!!输出:fields: []fields: [0x1040a120]fields: []fields: [0x1040a130]
查看完整描述

1 回答

?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

func (s *MyStruct) pointerMethod() { } // method on pointer

func (s MyStruct)  valueMethod()   { } // method on value

对于不习惯指针的程序员来说,这两个例子之间的区别可能会令人困惑,但情况其实很简单。在类型上定义方法时,接收器(在上面的示例中为 s)的行为就像它是方法的参数一样。将接收者定义为值还是指针是同一个问题,然后,函数参数应该是值还是指针。有几个考虑。


首先,也是最重要的,该方法是否需要修改接收器?如果是,则接收者必须是一个指针。(切片和映射充当引用,所以它们的故事有点微妙,但是例如要更改方法中切片的长度,接收者仍然必须是指针。)在上面的示例中,如果 pointerMethod 修改了s,调用者将看到这些更改,但 valueMethod 是使用调用者参数的副本(这是传递值的定义)调用的,因此调用者将看不到它所做的更改。


顺便说一句,指针接收器与 Java 中的情况相同,尽管在 Java 中指针隐藏在幕后;Go 的价值接收者是不寻常的。


二是对效率的考虑。如果接收器很大,例如一个大的结构,使用指针接收器会便宜得多。


接下来是一致性。如果该类型的某些方法必须有指针接收器,其余的也应该如此,因此无论如何使用该类型,方法集都是一致的。有关详细信息,请参阅方法集部分。


对于诸如基本类型、切片和小型结构之类的类型,值接收器非常便宜,因此除非方法的语义需要指针,否则值接收器是高效且清晰的。


在 Go 中,所有参数和返回值都是按值传递的。接收器按值传递。使用指针接收器更改值。例如,


package main


import (

    "fmt"

)


type Prompter interface {

    Define(f *Field)

}


type Field struct {

    Key string

}


type Provider interface {

    Prompt(Prompter)

}


var providers = []Provider{

    MyProvider{},

}


type MyProvider struct{}


func (p MyProvider) Prompt(prompter Prompter) {

    prompter.Define(&Field{"name"})

    prompter.Define(&Field{"age"})

}


type CliPrompter struct {

    fields []*Field

}


func NewCliPrompter() *CliPrompter {

    return &CliPrompter{

        fields: make([]*Field, 0, 100),

    }

}


func (c *CliPrompter) Define(f *Field) {

    fmt.Printf("fields: %+v\n", c.fields)

    c.fields = append(c.fields, f)

    fmt.Printf("fields: %+v\n", c.fields)

}


func main() {

    providers[0].Prompt(NewCliPrompter())

}

输出:


fields: []

fields: [0x1040a120]

fields: [0x1040a120]

fields: [0x1040a120 0x1040a130]


查看完整回答
反对 回复 2021-09-27
  • 1 回答
  • 0 关注
  • 212 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信