Go:通过interface{}指针传递返回值

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

Go: Passing a return value via an interface{} pointer

问题

我有一个函数,看起来像这样:

func Foo(result interface{}) error {
    ...
    json.Unmarshal([]byte(some_string), result)
    ...
}

它的调用方式如下:

var bar Bar
Foo(&bar)

通常情况下,Foo会获取一个字符串,然后将其解析为结果。然而,现在我需要更新它,使得Foo有时从另一个来源加载数据并返回。

type Loader func() interface{}

func Foo(result interface{}, load Loader) error {
    ...
    data := load()
    // result = data ???
    ...
}

有没有办法将这个新值赋给result?我发现我可以将数据编组为字符串,然后将其解组到result中,这样可以工作,但我无法想象这是最好的方法。

英文:

I have a function that looks like this:

func Foo(result interface{}) error {
     ...
     json.Unmarshal([]byte(some_string), result)
     ...
}

Which is called like this:

var bar Bar
Foo(&bar)

Generally, Foo fetches a string that is then unmarshalled into the result. However, now I need to update it so that Foo sometimes loads data from another source and returns that instead.

type Loader func() (interface{})

func Foo(result interface{}, Loader load) error {
     ...
     data := load()
     // result = data ???
     ...
}

Is there any way for me to assign this new value to result? I found that I can marshal the data into a string and then unmarshal it into result which works, but I can't imagine that's the best way.

答案1

得分: 5

你可以这样做:

p := result.(*Bar)
*p = data

第一行是一个类型断言(type assertion)。

第二行将data赋值给解引用的指针。将值赋给解引用的指针会改变引用地址处的值。

由于你不知道resultdata的底层类型,你最好使用类型断言的switch语句。

switch v := data.(type) {
case Bar:
    // 如果'data'的类型是'Bar'
    p, ok := result.(*Bar)
    if !ok {
        // 这意味着输入有误。
        // 'result'和'data'应该具有相同的底层类型。
        fmt.Println("底层类型不匹配")
        break
    }
    
    *p = v

case Baz:
    // 如果'data'的类型是'Baz'
    // 对于'Baz',与上面的代码等效
}

参见switch语句中的**类型开关(Type Switches)**部分。

英文:

You can do,

p := result.(*Bar)
*p = data

The first line is a type assertion.

The second assigns data to the dereferenced pointer. Assigning a value to a dereferenced pointer changes the value at the referenced address.

Since you don't know the underlying types of result or data the best you can do is using a type assertion switch.

switch v := data.(type) {
case Bar:
    // If 'data' is of type 'Bar'
	p, ok := result.(*Bar)
	if(!ok){
        // This means inputs were bad.
        // 'result' and 'data' should both have the same underlying type.
		fmt.Println("underlying types mismatch")
		break;
	}
	
	*p = v

case Baz:
    // If 'data' is of type 'Baz'
    // Equivalent of above for 'Baz'
}

See Type Switches from switch statement

huangapple
  • 本文由 发表于 2016年4月6日 17:17:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/36446675.html
匿名

发表评论

匿名网友

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

确定