我需要知道该结构或该结构的指针是否实现了给定的接口。
// 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
还是{{1 }}实现。
我为什么要那样?因为如果可以的话,程序员不需要知道A
的工作方式。如果不是这样,那么程序员应该始终需要将指针传递给Serializable
并在结构指针而不是结构本身中实现Serializable
。
答案 0 :(得分:1)
当用户给您*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`来编写无副本的版本代码是很容易的。但这是极不推荐的:它很可能会破坏您将来的代码,并且难以维护。它使用引擎盖下的不安全包装。
答案 1 :(得分:0)
func Serialize(objInt interface{}) []byte {
switch v := objInt.(type) {
case Serializable:
return v.Serializebyte()
}
// do stuf on object that do not implement Serializebyte
}