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

huangapple go评论65阅读模式
英文:

If the type of a parameter is interface{} how do you know whether you pass by pointer or by value?

问题

对于接受 interface{} 类型参数的任何函数,如何知道是否需要带上 & 来传递参数,而不需要查看函数的源代码呢?

例如,如果我有一个给出以下类型签名的函数:

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

有没有办法确定 x 是按值传递还是按指针传递的呢?

英文:

Given any function that takes a parameter of type interface{} how would I know whether or not to pass that parameter with or without & without navigating the source code of the function.

For example if I had a function with this type signature given to me:

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

Would there be any way to figure out if x was supposed to be passed by value or by pointer?

答案1

得分: 3

以下是源代码片段的翻译:

// DecodeElement的功能类似于Unmarshal,但它接受一个指向开始XML元素的指针来解码为v。
// 当客户端自己读取一些原始的XML标记,但也想将某些元素推迟到Unmarshal时,它非常有用。

func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
    val := reflect.ValueOf(v)
    if val.Kind() != reflect.Ptr {
        return errors.New("传递给Unmarshal的非指针")
    }
    return d.unmarshal(val.Elem(), start)
}

它检查了val.Kind() != reflect.Ptr,这意味着你必须传递指针,即&v

这完全取决于编写该方法或函数的人,所以interface{}可以是*ptr或其他任何类型,但你必须在函数内部使用reflect.ValueOf(v).Kind()检查该值是否为指针,并相应地进行处理。

关于空接口的一点说明:

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

interface{}

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

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

另一个有用的讨论:文档

英文:

Here is the snippet from the source:

// 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)
}

It is checking val.Kind() != reflect.Ptr Which means you have to pass the pointer i.e &v.

Its entirely depend on the person who wrote the method or function, so interface{} could be either *ptr or anything but u ve to check that inside your function using reflect.ValueOf(v).Kind() whether the value is a pointer or not and proceeds accordingly.

And little bit about empty interface:

The interface type that specifies zero methods is known as the empty interface:

interface{}

An empty interface may hold values of any type. (Every type implements at least zero methods.)

Empty interfaces are used by code that handles values of unknown type. For example, fmt.Print takes any number of arguments of type interface{}.

Another useful discussion: docs

答案2

得分: 1

DecodeElement()和相关函数有一个正式的v interface{}参数,其类型在Unmarshal()函数的文档中有详细说明:

> Unmarshal函数解析XML编码的数据,并将结果存储在指向v的值中,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)

但是

xmlDecoder.DecodeElement(b, startElement)
英文:

DecodeElement() and friends have a formal v interface{} whose type is documented in the Unmarshal() function documentation:

> Unmarshal parses the XML-encoded data and stores the result in the
> value pointed to by v, which must be an arbitrary struct, slice, or
> string.

So to literally answer your question, no, you cannot know without reading the source - if the value you want to pass is a struct proper, you need to indirect. If it is already a pointer to that struct, you do not.

For example:

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)

but

xmlDecoder.DecodeElement(b, startElement)

huangapple
  • 本文由 发表于 2017年1月9日 12:27:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/41541040.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定