dongxian7194 2019-02-07 01:38 采纳率: 0%
浏览 12
已采纳

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

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.

  • 写回答

2条回答 默认 最新

  • duandong9195 2019-02-07 05:26
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 vue3加ant-design-vue无法渲染出页面
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序