下面是一个简单的围棋程序,但它不能正常工作:
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
fmt.Println(getProperty(&v, "X"))
}
func getProperty(v *Vertex, property string) (string) {
return v[property]
}
错误:
程序执行:18:无效操作:v [特性](类型索引 * 顶点)
我想要的是使用它的名字来访问Vertex X属性。如果我使用v.X
,它会工作,但是v["X"]
不会。
有人能告诉我怎么做吗?
5条答案
按热度按时间bksxznpy1#
大多数代码都不需要这种动态查找,与直接访问相比效率很低(编译器知道Vertex结构中X字段的偏移量,它可以将v.X编译成一条机器指令,而动态查找需要某种哈希表实现或类似的东西),它还抑制了静态类型:编译器无法检查您是否试图动态访问未知字段,并且它无法知道结果类型应该是什么。
但是...该语言提供了一个reflect模块,以满足您在极少数情况下的需要。
这里没有错误检查,所以如果您请求一个不存在的字段,或者该字段不是int类型,您将得到一个异常。
qni6mghb2#
现在您有了项目oleiade/reflections,它允许您获取/设置结构值或指针上的字段。
这使得使用
reflect
package不那么棘手。b1payxdu3#
使用
getAttr
,您可以轻松获取和设置。在
上运行👉
参考
vhmi4jdf4#
你可以封送这个结构体,然后将它解组回
map[string]interface{}
,但是,它会将所有的数值转换成float64
,所以你必须手动将它转换成int
。up9lanfz5#
我想提供一种不使用反射的不同方法:
https://go.dev/play/p/2E7LZBWx7yZ
这是一个
O(1)
Map查找和一个函数调用,应该比反射执行得更好。显然,你需要一些脚手架代码来支持每一个你想要支持的类型。从好的方面来说,你可以很容易地重构你的代码;您的函数getProperty
可能是https://martinfowler.com/bliki/TellDontAsk.html的反模式