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
没有明确的文档,您无论如何都不应该称之为它。