go - 如何知道结构或指向结构的指针是否实现接口
问题描述
我需要知道结构或指向该结构的指针是否实现了给定的接口。
// 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`可以编写免拷贝版本代码。但强烈不推荐:它很可能会破坏您未来的代码并且难以维护;它在引擎盖下使用了不安全的包。
推荐阅读
- reactjs - 博览会在本机应用程序中启动时出错(样式表)
- mips - 如何让我的代码添加两个数字以在 QtSpim 中工作?
- selenium-webdriver - “未能找到 Chrome 二进制文件。” 在系统规范 gitlab-ci
- c# - 使用按钮在 Unity 中启动粒子系统
- typescript - 打字稿:传递类函数时如何检查它们是否绑定
- python - 如何在 Angr 程序的开头添加字符串输入?
- r - 将列名转换为行值并求和
- c# - EF Core Eager 加载返回 null
- javascript - 有没有办法修复 gulp 中的 assert.js:385 错误?
- python - 数组大小不匹配