将结构体指针转换为interface{}

43
如果我有:
   type foo struct{
   }

   func bar(baz interface{}) {
   }
上述内容是不可更改的 - 我无法更改foo或bar。此外,在调用bar时,必须将baz转换回foo结构体指针。如何将 &foo{} 转换为 interface{},以便在调用bar时将其用作参数?
4个回答

78
*foo转换为interface{}是微不足道的:
f := &foo{}
bar(f) // every type implements interface{}. Nothing special required

要返回到 *foo,你可以使用类型断言

func bar(baz interface{}) {
    f, ok := baz.(*foo)
    if !ok {
        // baz was not of type *foo. The assertion failed
    }

    // f is of type *foo
}

或者使用类型开关(类似,但如果baz可以是多种类型,则很有用):

func bar(baz interface{}) {
    switch f := baz.(type) {
    case *foo: // f is of type *foo
    default: // f is some other type
    }
}

如果您不知道接口的类型怎么办?例如您的示例中的 baz - Juan de Parras
7
如果你不知道baz可能是哪种类型,那么你就需要使用反射(import "reflect")。这也是像encoding/json这样的包可以在不预先知道任何类型的情况下对基本上任何类型进行编码的方式。 - ANisus
有没有使用切片的方法来实现这个? - jocull
我不明白。你正在发送一个带有结构体foo地址的对象,但是在函数中它接受一个接口?当我尝试这样做并使用fmt.Printf打印类型时,它说类型是结构体指针,而不是接口.... - Saim Mahmood
1
@SaimMahmood fmt.Printf总是将其参数作为接口接收。它告诉您接口内部的类型。这意味着fmt.Printf(“%T”,f)fmt.Printf(“%T”,interface {}(f))是相同的。唯一的区别在于,在后者中,我进行了冗余的显式转换。 - ANisus

6

使用 reflect

reflect.ValueOf(myStruct).Interface().(newType)

4
reflect 可以做到这一点,但这是一种繁琐而危险的转换方式。在被接受的答案中描述了一种更简单的方法。 - alexykot

2
将结构体转换为接口可以通过以下方式实现。 其中i是一个分配的数据结构。
var j interface{} = &i

这应该是正确的答案,因此从问题中可以得出类似以下的内容:var newFoo interface{} = &foo{}bar(newFoo) - tyohan

0

虽然不是完全相关的,但我在谷歌上搜索了“将接口结构转换为指针”的问题,并找到了这里。

所以,只需记住:要将 T 的接口 转换为 *T 的接口

//
// Return a pointer to the supplied struct via interface{}
//
func to_struct_ptr(obj interface{}) interface{} {
    vp := reflect.New(reflect.TypeOf(obj))
    vp.Elem().Set(reflect.ValueOf(obj))
    return vp.Interface()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接