Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在go(golang)中,如何将接口指针强制转换为结构指针?_Go - Fatal编程技术网

在go(golang)中,如何将接口指针强制转换为结构指针?

在go(golang)中,如何将接口指针强制转换为结构指针?,go,Go,我想使用一些需要指向结构的指针的外部代码。在调用代码时,我有一个接口变量 在创建该变量的指针时,指针的类型是interface{}*,而我需要它作为结构类型的指针类型 想象一下,TestCanGetStructPointer中的代码不知道Cat类,并且它存在于某个外部包中 我怎样才能做到这一点 下面是一个代码示例: import ( "reflect" "testing" ) type Cat struct { name string } type Someth

我想使用一些需要指向结构的指针的外部代码。在调用代码时,我有一个接口变量

在创建该变量的指针时,指针的类型是
interface{}*
,而我需要它作为结构类型的指针类型

想象一下,
TestCanGetStructPointer
中的代码不知道Cat类,并且它存在于某个外部包中

我怎样才能做到这一点

下面是一个代码示例:

import (
    "reflect"
    "testing"
)   

type Cat struct {
    name string
}

type SomethingGeneric struct {
    getSomething func() interface{}
}

func getSomeCat() interface{} {
    return Cat{}
}

var somethingForCats = SomethingGeneric{getSomething: getSomeCat}

func TestCanGetStructPointer(t *testing.T) {
    interfaceVariable := somethingForCats.getSomething()

    pointer := &interfaceVariable

    interfaceVarType := reflect.TypeOf(interfaceVariable)
    structPointerType := reflect.PtrTo(interfaceVarType)
    pointerType := reflect.TypeOf(pointer)

    if pointerType != structPointerType {
        t.Errorf("Pointer type was %v but expected %v", pointerType, structPointerType)
    }

}
测试失败,原因是:

指针类型为*接口{},但应*参数化。Cat

以下内容可能会有所帮助:


@dyoo的示例确实有效,但它依赖于您手动施放
Dog
Cat

下面是一个复杂/冗长的示例,在某种程度上避免了该约束:

package main

import (
    "fmt"
    "reflect"
)

type Cat struct {
    name string
}

type SomethingGeneric struct {
    getSomething func() interface{}
}

func getSomeCat() interface{} {
    return Cat{name: "Fuzzy Wuzzy"}
}

var somethingForCats = SomethingGeneric{getSomething: getSomeCat}

func main() {
    interfaceVariable := somethingForCats.getSomething()
    castVar := reflect.ValueOf(interfaceVariable)
    castVar.Convert(castVar.Type())

    // If you want a pointer, do this:
    fmt.Println(reflect.PtrTo(castVar.Type()))

    // The deref'd val
    if castVar.Type() != reflect.TypeOf(Cat{}) {
        fmt.Printf("Type was %v but expected %v\n", castVar, reflect.TypeOf(&Cat{}))
    } else {
        fmt.Println(castVar.Field(0))
    }
}
我找到了这个线程:


x:=somethingForCats.getSomething()(Cat)&x
除非将
返回Cat{}
更改为
返回&Cat{}
返回新(Cat)
,然后只需
somethingForCats.getSomething()。(*Cat)
@DaveC呃,可以稍微玩一下,但对性能来说肯定不是很好:@DaveC运行此代码的地方不知道Cat类型,所以它不能直接到该类型。此外,此代码需要用于getSomething()返回的任何类型。它适用于单独包中的代码。您需要将一个指向接口的指针传递到这个外部包中。@OvedD然后编辑您的问题。第一段当前说您有一个
接口{}
,需要一个
*structType
才能传递到其他地方。类型断言是实现这一点的最简单方法。运行此断言的代码没有访问Cat或Dog类的权限
package main

import (
    "fmt"
    "reflect"
)

type Cat struct {
    name string
}

type SomethingGeneric struct {
    getSomething func() interface{}
}

func getSomeCat() interface{} {
    return Cat{name: "Fuzzy Wuzzy"}
}

var somethingForCats = SomethingGeneric{getSomething: getSomeCat}

func main() {
    interfaceVariable := somethingForCats.getSomething()
    castVar := reflect.ValueOf(interfaceVariable)
    castVar.Convert(castVar.Type())

    // If you want a pointer, do this:
    fmt.Println(reflect.PtrTo(castVar.Type()))

    // The deref'd val
    if castVar.Type() != reflect.TypeOf(Cat{}) {
        fmt.Printf("Type was %v but expected %v\n", castVar, reflect.TypeOf(&Cat{}))
    } else {
        fmt.Println(castVar.Field(0))
    }
}
package main

import (
    "fmt"
    "reflect"
)

type Cat struct {
    name string
}

//
// Return a pointer to the supplied struct via interface{}
//
func to_struct_ptr(obj interface{}) interface{} {

    fmt.Println("obj is a", reflect.TypeOf(obj).Name())

    // Create a new instance of the underlying type 
    vp := reflect.New(reflect.TypeOf(obj))

    // Should be a *Cat and Cat respectively
    fmt.Println("vp is", vp.Type(), " to a ", vp.Elem().Type())

    vp.Elem().Set(reflect.ValueOf(obj))

    // NOTE: `vp.Elem().Set(reflect.ValueOf(&obj).Elem())` does not work

    // Return a `Cat` pointer to obj -- i.e. &obj.(*Cat)
    return vp.Interface()
}

//
// Dump out a pointer ...
//
func test_ptr(ptr interface{}) {
    v := reflect.ValueOf(ptr)
    fmt.Println("ptr is a", v.Type(), "to a", reflect.Indirect(v).Type())
}

func main() {
    cat := Cat{name: "Fuzzy Wuzzy"}

    // Reports "*main.Cat"
    test_ptr(&cat)

    // Get a "*Cat" generically via interface{}
    sp := to_struct_ptr(cat)

    // *should* report "*main.Cat" also
    test_ptr(sp)

    fmt.Println("sp is",sp)
}