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

I need to know if either the struct or the pointer to that struct implements a given 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
")
  return v.Serializebyte()
 }

 fmt.Printf("I'm not Serializable
")
 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
")
        return objInt.(Serializable).Serializebyte()
}

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



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

Edit: You can run the code above to see what I mean.

Because (*A) implements Serializable not A, the assertion above does not pass but I want to know if either (*A) implements Serializable or A implements it.

Why do I want that? Because if I can do that, the programmers do not need to know how Serializable works. If not the programers should always need to pass a pointer to Serializable and implement Serializable in the struct pointer rather than the struct itself.

It is usually a bad idea to use *T when the user gives you T. All modifies on *T will NOT take effect on user's data.

But if that is what you really want, you can use reflect.

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)
}

Playground: https://play.golang.org/p/rqJe5_KAP6e

EDIT:If you need to make use of that method with pointer reciever, you can use reflect.Value instead of reflect.Type. However, it makes an extra copy of the param.

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
}

It is hackable to write a copy-free version code by using refelct.NewAt and ·reflect.Value.InterfaceData`. But it is highly un-recommended: It will very likely break your future code and is hard to maintain; It uses unsafe package under the hood.

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