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

时间:2017-01-09 04:27:47

标签: pointers go

给定任何带有interface{}类型参数的函数如何在不导航函数源代码的情况下知道是否使用&传递该参数。

例如,如果我有一个给我这种类型签名的函数:

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

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

2 个答案:

答案 0 :(得分:2)

以下是来自源代码的片段:

// 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这意味着您必须通过指针,即& v。

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

<强> And little bit about empty interface:

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

interface{}

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

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

另一个有用的讨论:docs

答案 1 :(得分:1)

DecodeElement()和朋友有一个正式v interface{},其类型记录在Unmarshal()函数documentation中:

  

Unmarshal解析XML编码的数据并将结果存储在   v指向的值,它必须是任意的struct,slice或   字符串。

所以要从字面上回答你的问题,不,你不知道没有阅读源 - 如果你要传递的值是一个结构本身,你需要间接。如果它已经是指向该结构的指针,那么你就不会。

例如:

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)

xmlDecoder.DecodeElement(b, startElement)