【问题标题】:Pointer to loop variable for range over map or slice of interface{}指向地图或接口切片范围的循环变量的指针{}
【发布时间】: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?我怀疑您的问题是由于H5Awritev 解释为其他东西。特别是它可能正在寻找一个整数或类似的东西,并获得一个接口值。
  • 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


【解决方案1】:

Write 方法需要一个指向值的指针,而不是指向包含该值的接口的指针。您可以使用反射获得它:

u := reflect.New(reflect.ValueOf(v).Type())
u.Elem().Set(reflect.ValueOf(v))
v := u.Interface()

【讨论】:

    猜你喜欢
    • 2018-10-07
    • 2017-10-03
    • 1970-01-01
    • 2015-05-01
    • 2017-07-04
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多