指向循环变量的指针,用于遍历接口{}类型的映射或切片。

huangapple go评论89阅读模式
英文:

Pointer to loop variable for range over map or slice of interface{}

问题

我正在使用go-hdf5,在尝试从映射中循环写入属性时遇到了问题。

属性被正确创建(正确的名称和数据类型),但写入的值是垃圾值。

在循环之外使用相同的代码可以正常工作。我尝试过使用v := v的习惯用法,以及将代码包装在闭包中以捕获v,但没有任何区别。

以下是代码的要点(为了清晰起见,省略了错误检查):

m := map[string]interface{}{"foo": 42}
for k, v := range m {
	// [...]
	v := v
	attr.Write(&v, dtype)
}

Write方法使用反射来获取值的指针,并将其传递给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。

英文:

I'm using go-hdf5 and I'm hitting a problem when trying to write attributes in a loop from a map.

The attributes are created correctly (correct name and datatype) but the written value is garbage.

The same code outside of the loop works fine. I tried both the v := v idiom and wrapping the code in a closure to capture v but it doesn't make a difference.

Here is the gist of the code (error checking intentionally left out for clarity):

m := map[string]interface{"foo", 42}
for k, v := range m {
	// [...]
	v := v
	attr.Write(&v, dtype)
}

The Write method is using reflection to grab a pointer to the value and forwards it to the C library. The relevant part of the code is just:

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))
}

If I replace the map by a slice of interface{}, I get the exact same problem so my hunch is that this has to do with the binding of loop variables, but yet v := v doesn't help so I'm not sure.

I'm quite familiar with Go, HDF5 (C library) and go-hdf5 but I'm really stuck here. Any idea?

BTW I'm using go1.5.1 darwin/amd64.

答案1

得分: 0

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

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

The Write method needs a pointer to a value, not a pointer to an interface containing the value. You can get it using reflection:

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

huangapple
  • 本文由 发表于 2016年2月27日 01:44:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/35658354.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定