【发布时间】:2016-02-26 17:44:03
【问题描述】:
我正在使用go-hdf5,但在尝试从地图循环写入属性时遇到了问题。
属性创建正确(名称和数据类型正确),但写入的值是垃圾。
循环外的相同代码可以正常工作。我尝试了v := v 习惯用法并将代码包装在一个闭包中以捕获v,但这并没有什么不同。
这里是代码的要点(为了清楚起见,故意省略了错误检查):
m := map[string]interface{"foo", 42}
for k, v := range m {
// [...]
v := v
attr.Write(&v, dtype)
}
Write method 正在使用反射来获取指向该值的指针并将其转发到 C 库。代码的相关部分只是:
func (s *Attribute) Write(data interface{}, dtype *Datatype) error {
v := reflect.ValueOf(data)
addr := unsafe.Pointer(v.Pointer())
return h5err(C.H5Awrite(s.id, dtype.id, addr))
}
如果我用interface{} 的一部分替换地图,我会遇到完全相同的问题,所以我的直觉是这与循环变量的绑定有关,但是v := v 没有帮助,所以我我不确定。
我对 Go、HDF5(C 库)和 go-hdf5 非常熟悉,但我真的被困在这里。有什么想法吗?
顺便说一句,我正在使用 go1.5.1 darwin/amd64。
【问题讨论】:
-
什么是
dtype?我怀疑您的问题是由于H5Awrite将v解释为其他东西。特别是它可能正在寻找一个整数或类似的东西,并获得一个接口值。 -
dtype是接口值的正确类型的hdf5.Datatype。似乎将v类型转换为正确的类型(例如,将v := v替换为v := v.(int))有效。当然,我不应该知道正确的类型(除了通过反射)。 -
首先,你确定你得到了指向正确结构的指针吗?您使用指向接口的指针调用
Write,这几乎总是不正确的。其次,Write是否存储了对指针的引用?如果在 Go 中不维护对指针的引用,则在将其传递给 C 之后,v的值将被 GC'ed。 (另外,使用 go1.6 运行,它为 cgo 代码添加了额外的安全检查) -
C 库要么刷新要么保留它自己的值副本,所以我很确定 GC 不是问题。我认为你是对的,我需要提供一个指向值本身的指针。那我可能需要使用反射。
-
哦,是的,我没有仔细阅读示例的第二部分。您肯定只是使用指向接口的指针,而不是值。
标签: go hdf5 unsafe-pointers