首页 > 解决方案 > 如何知道结构或指向结构的指针是否实现接口

问题描述

我需要知道结构或指向该结构的指针是否实现了给定的接口。

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
 var a A = A{
  i: 5,
 }
 Serialize(a)
 Serialize(&a)
}

type Serializable interface {
 //Serialize() string
 //Deserialize(string)

 Serializebyte() []byte
 Deserializebyte(b []byte) (bytesRead int)
}

type A struct {
 i int
}

func (*A) Serializebyte() []byte {
 return []byte{0x00}
}

func (*A) Deserializebyte(b []byte) (bytesRead int) {
 return 0
}

func Serialize(objInt interface{}) []byte {
 // this doesn't work

 switch v := (objInt).(type) {
 case Serializable:
  fmt.Printf("I'm Serializable\n")
  return v.Serializebyte()
 }

 fmt.Printf("I'm not Serializable\n")
 return []byte{0x00}
}

// this other way also dont work
func Serialize2(objInt interface{}) []byte {
// this doesn't work
    _, isSerializable := objInt.(Serializable)
    if isSerializable{
        fmt.Printf("I'm Serializable\n")
        return objInt.(Serializable).Serializebyte()
}

    fmt.Printf("I'm not Serializable\n")
    return []byte{0x00}
}



// Stdout:
// I'm not Serializable
// I'm Serializable

编辑: 您可以运行上面的代码来了解我的意思。

因为没有(*A)实现,所以上面的断言没有通过,但我想知道是实现还是实现了它。SerializableA(*A)SerializableA

我为什么要那个?因为如果我能做到这一点,程序员就不需要知道它是如何Serializable工作的。如果不是,程序员应该总是需要传递一个指针SerializableSerializable在结构指针中实现,而不是结构本身。

标签: goreflection

解决方案


*T当用户给你时使用它通常是一个坏主意T。所有修改都不*T会对用户数据生效。

但如果那是你真正想要的,你可以使用反射。

func testFool(a interface{}) bool {
    if _, ok := a.(Fool); ok {
        return true
    }
    t := reflect.PtrTo(reflect.TypeOf(a))
    FoolType := reflect.TypeOf((*Fool)(nil)).Elem()
    return t.Implements(FoolType)
}

游乐场: https: //play.golang.org/p/rqJe5_KAP6e

编辑:如果您需要通过指针接收器使用该方法,您可以使用reflect.Value代替reflect.Type. 但是,它会制作一个额外的参数副本。

func testFool(a interface{}) bool {
    if _, ok := a.(Fool); ok {
        return true
    }
    t := reflect.TypeOf(a)
    v := reflect.New(t)
    v.Elem().Set(reflect.ValueOf(a))
    ptrA := v.Interface()
    if foo, ok := ptrA.(Fool); ok {
        foo.Foo()
        return true
    }
    return false
}

refelct.NewAt使用和·reflect.Value.InterfaceData`可以编写免拷贝版本代码。但强烈不推荐:它很可能会破坏您未来的代码并且难以维护;它在引擎盖下使用了不安全的包。


推荐阅读