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

Go 为什么我的字段在函数调用后被截断?,go,Go,我已经试了两个小时了。进入主功能,我们立即进入第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数组再次为空!!!输出: field

我已经试了两个小时了。进入主功能,我们立即进入第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]
围棋编程语言

对于不习惯使用指针的程序员来说 这两个例子可能会让人困惑,但实际情况却是如此 很简单。在类型上定义方法时 上面的示例)的行为与 方法是否将接收器定义为值或指针是不确定的 同样的问题,比如函数参数是否应该是 值或指针。有几个考虑因素

首先,也是最重要的,该方法是否需要修改 接受者如果是,则接收器必须是指针。(切片和地图) 作为参考,这样他们的故事就更微妙了,但是 实例来更改接收方必须执行的方法中切片的长度 在上面的示例中,如果pointerMethod修改 s的字段,调用方将看到这些更改,但valueMethod是 使用调用方参数的副本调用(这是 传递一个值),因此它所做的更改对调用方不可见

顺便说一下,指针接收器与Java中的情况相同, 尽管在Java中,指针隐藏在盖子下面;它是去的 不寻常的价值接受者

二是效率的考虑。如果接收器较大,则为 例如,使用指针会便宜得多 接受者

其次是一致性。如果该类型的某些方法必须具有 指针接收器,其余的也应该是,因此方法集是 无论类型如何使用,都是一致的。请参阅上的一节 方法集以获取详细信息

对于基本类型、切片和小型结构等类型,值 接收方非常便宜,所以除非方法的语义需要 一个指针,一个值接收器是高效和清晰的

在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]
fields: []
fields: [0x1040a120]
fields: [0x1040a120]
fields: [0x1040a120 0x1040a130]