繁体   English   中英

如何知道结构体或结构体指针是否实现了接口

[英]How to know if a struct or pointer to struct implements an interface

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

// 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)实现了Serializable而不是A ,上面的断言没有通过,但我想知道是(*A)实现了Serializable还是A实现了它。

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

当用户给你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` 编写免拷贝版本代码是可以破解的。 但是非常不推荐:它很可能会破坏您未来的代码并且难以维护; 它在引擎盖下使用不安全的包。

func Serialize(objInt interface{}) []byte {
    switch v := objInt.(type) {
    case Serializable:
        return v.Serializebyte()
    }

    // do stuf on object that do not implement Serializebyte
}

https://tour.golang.org/methods/16

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM