Pointers 如果参数的类型是接口{},您如何知道是通过指针还是通过值传递?

Pointers 如果参数的类型是接口{},您如何知道是通过指针还是通过值传递?,pointers,go,Pointers,Go,给定任何接受接口{}类型参数的函数,在不浏览函数源代码的情况下,我如何知道是否通过&传递该参数 例如,如果我有一个具有此类型签名的函数: func foo(x interface{}, y int) int 有没有办法弄清楚x应该是通过值还是指针传递的?下面是源代码的片段: // DecodeElement works like Unmarshal except that it takes // a pointer to the start XML element to decode into

给定任何接受
接口{}
类型参数的函数,在不浏览函数源代码的情况下,我如何知道是否通过
&
传递该参数

例如,如果我有一个具有此类型签名的函数:

func foo(x interface{}, y int) int

有没有办法弄清楚x应该是通过值还是指针传递的?

下面是源代码的片段:

// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.

func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
    val := reflect.ValueOf(v)
    if val.Kind() != reflect.Ptr {
        return errors.New("non-pointer passed to Unmarshal")
    }
    return d.unmarshal(val.Elem(), start)
}
它正在检查
val.Kind()!=reflect.Ptr
这意味着您必须传递指针,即e&v

它完全取决于编写方法或函数的人,因此
接口{}
可以是*ptr或任何东西,但必须使用
reflect.ValueOf(v.Kind()
检查函数内部的值是否为指针,并相应地进行处理

指定零方法的接口类型称为空接口:

接口{}

空接口可以保存任何类型的值。(每种类型至少实现零个方法。)

处理未知类型值的代码使用空接口。例如,fmt.Print接受任意数量的
interface{}
类型的参数


另一个有用的讨论:

以下是源代码的片段:

// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.

func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
    val := reflect.ValueOf(v)
    if val.Kind() != reflect.Ptr {
        return errors.New("non-pointer passed to Unmarshal")
    }
    return d.unmarshal(val.Elem(), start)
}
它正在检查
val.Kind()!=reflect.Ptr
这意味着您必须传递指针,即e&v

它完全取决于编写方法或函数的人,因此
接口{}
可以是*ptr或任何东西,但必须使用
reflect.ValueOf(v.Kind()
检查函数内部的值是否为指针,并相应地进行处理

指定零方法的接口类型称为空接口:

接口{}

空接口可以保存任何类型的值。(每种类型至少实现零个方法。)

处理未知类型值的代码使用空接口。例如,fmt.Print接受任意数量的
interface{}
类型的参数

另一个有用的讨论:

decodelement()
和friends有一个正式的
v接口{}
,其类型记录在
Unmarshal()
函数中:

解组器解析XML编码的数据并将结果存储在 v指向的值,该值必须是任意结构、切片或 绳子

因此,要从字面上回答您的问题,不,您必须阅读源代码才能知道-如果您想要传递的值是一个结构本身,那么您需要间接的。如果它已经是指向该结构的指针,则不需要

例如:

type Result struct {
    XMLName xml.Name `xml:"Person"`
    Name    string   `xml:"FullName"`
    Phone   string
    Email   []Email
    Groups  []string `xml:"Group>Value"`
    Address
}

var (
    a Result
    b *Result
    c string
)

xmlDecoder.DecodeElement(&a, startElement)
xmlDecoder.DecodeElement(&c, startElement)
但是

decodelement()
和friends有一个正式的
v接口{}
,其类型记录在
Unmarshal()
函数中:

解组器解析XML编码的数据并将结果存储在 v指向的值,该值必须是任意结构、切片或 绳子

因此,要从字面上回答您的问题,不,您必须阅读源代码才能知道-如果您想要传递的值是一个结构本身,那么您需要间接的。如果它已经是指向该结构的指针,则不需要

例如:

type Result struct {
    XMLName xml.Name `xml:"Person"`
    Name    string   `xml:"FullName"`
    Phone   string
    Email   []Email
    Groups  []string `xml:"Group>Value"`
    Address
}

var (
    a Result
    b *Result
    c string
)

xmlDecoder.DecodeElement(&a, startElement)
xmlDecoder.DecodeElement(&c, startElement)
但是


事实上,我自己在提问之前就发现了这一点。也许我的问题应该更具体一些,但我的意思是,不检查源代码有什么办法吗?至少你应该检查文档:文档中明确提到:
decodelement的工作原理与Unmarshal类似,只是它需要指向start XML元素的指针才能解码为v
James你希望我在我的原始问题中更改函数签名吗?我并不是特别谈论
decodelement
,而是任何带有
interface{}
作为参数类型的函数。好吧,如果是这样的话,那么interface{}可以是任何东西,它完全取决于编写方法或函数的人。事实上,我自己在提问之前就遇到过这个问题。也许我的问题应该更具体一些,但我的意思是,不检查源代码有什么办法吗?至少你应该检查文档:文档中明确提到:
decodelement的工作原理与Unmarshal类似,只是它需要指向start XML元素的指针才能解码为v
James你希望我在我的原始问题中更改函数签名吗?我不是专门谈论
decodelement
,而是任何带有
interface{}
作为参数类型的函数。好吧,如果是这样的话,那么interface{}可以是任何东西,它完全取决于编写方法或函数的人。aaaa当然,正如James在他的(编辑版)中指出的那样回答:当然,您可以完全使用反射来评估所讨论的值是否实际上是指向struct的指针,并且您可以随后使用间接的&很好。所以,我想我的答案是“字面上”不正确!AAAA当然,正如James在他的(编辑的)回答中指出的那样,你当然可以完全使用反射来评估所讨论的值是否实际上是指向struct的指针,并且你可以随后实际上间接地使用&just fine。所以,我想我的答案是“字面上”不正确!好吧,这很简单:您阅读了
foo
的文档!我知道这对很多人来说很奇怪,但是是的,你就是这么做的!如果
foo
没有清晰的文档,你无论如何也不应该称之为它。好吧,这很简单:你阅读
foo
的文档!我知道这对很多人来说很奇怪,但是是的,你就是这么做的!如果
foo
没有明确的文档,您无论如何都不应该称之为它。