No, I don't think this is a duplicate of
How to determine an interface{} values"real" type?. I know how to get the Type of an interface variable, but I can't find a way to get the pointer to an interface{}'s real type.

最近,我遇到了interface{}的麻烦。 我有一个类型A的变量通过interface{}传递,方法Tt被定义为* A作为接收者。

我想调用方法Tt,但是失败了,因为变量在interface{}中,并且我无法获得指向变量的指针。

如您所见,reflect.TypeOf(v)给出正确的类型A,但是reflect.TypeOf(&v)给出*interface {}而不是*A

有什么方法可以获取*A吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import (
   "fmt"
   "reflect"
)

type SomeStruct1 struct{
}

type SomeStruct2 struct{
}

type SomeStruct3 struct{
}
etc...

func (*SomeStruct1) SomeMethod(){
    fmt.Println("hello")
}
func (*SomeStruct2) SomeMethod(){
    fmt.Println("hello")
}
func (*SomeStruct3) SomeMethod(){
    fmt.Println("hello")
}
etc...

func DoSomething(arg interface{}){
    switch v:=b.(type){
        []byte:{
            dosomething for []byte
        }
        default:{
            var m reflect.Value
            if value.Kind() != reflect.Ptr {
                m = reflect.ValueOf(&v).MethodByName("SomeMethod")
            } else {
                m = reflect.ValueOf(v).MethodByName("SomeMethod")
            }
            m.Call(nil)
        }
}

func main() {
    DoSomething([]byte{...})
    DoSomething(SomeStruct1{})
    DoSomething(&SomeStruct1{})
    etc..
}
  • 使用反射包
  • 如何确定interface {}值"真实"类型的可能重复项?
  • 为什么不将方法Tt放在界面中并完成呢? 不使用任何反射?
  • 请提供一个合理的例子。 即使打算在这里似乎对我来说也错
  • @Yerken,我已进行编辑以提供更详细的示例。 我希望函数DoSomething接受SomeStruct*SomeStruct

使用反射:

1
2
3
4
5
6
7
8
//
// 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()
}

T传递interface,则可以用*T获得interface


要调用指针方法Tt(),您必须具有*A(或采用可寻址的A值的地址)。 变量b中的A值不可寻址,因此无法通过b访问A指针方法。

解决方法是从A地址开始:

1
2
3
4
5
6
7
var a A
var b interface{}
b = &a // Note change on this line
switch v := b.(type) {
default:
    reflect.ValueOf(v).MethodByName("Tt").Call(nil)
}

在调用reflect.ValueOf(v)中,v中的值作为参数传递。 ValueOf函数解压缩空接口以恢复类型为A的值。

在调用reflect.ValueOf(&v)中,*interface{}存储在空接口中,然后将其作为参数传递。 ValueOf函数解压缩空接口以恢复类型为*interface{}的值。 这是变量v的地址,而不是变量A的地址。

在此特定示例中,不需要反射:

1
2
3
4
5
6
7
8
9
10
11
var a A
var b interface{}
b = &a
switch v := b.(type) {
case interface {
    Tt()
}:
    v.Tt()
default:
    fmt.Println("not handled")
}
  • 是的,那行得通。 但是我确实认为reflect.ValueOf(v)Areflect.ValueOf(&v)* interface{}很奇怪
  • 我在答案中添加了更多解释。

您只需要键入强制类型转换。
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type SomeStruct1 struct{
    someList []string
}

func (s *SomeStruct1) print() {
    fmt.Printf("%v
", s.someList)
...

func Call(T interface{}){
    switch T.(type){
    case *SomeStruct1:
        t := T.(*SomeStruct1) // cast as pointer to struct
        t.print()
    ...
    }
}

func main() {
    a := SomeStruct{
        someList: []string{"a","b"}
    }
    Call(&a) // pass a as ptr
}