使用反射在Go中设置切片索引。

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

Set slice index using reflect in Go

问题

我在Go语言中使用reflect.Value表示一个切片。我有以下代码:

slice := reflect.MakeSlice(typ, len, cap)

如果我想从slice中获取第i个值,很简单:

v := slice.Index(i) // 返回一个reflect.Value

然而,我似乎找不到一种方法来设置第i个值。reflect.Value有很多的setter方法,例如,如果我有一个映射m,可以这样做:

m.SetMapIndex(key, value) // key和value的类型为reflect.Value

但是对于切片似乎没有类似的方法。我想到的一个可能是,也许从slice.Index(i)返回的值实际上是一个指针,所以调用v := slice.Index(i); v.Set(newV)会起作用?我不确定。有什么想法吗?

英文:

I'm in Go, working with a reflect.Value representation of a slice. I have the following:

slice := reflect.MakeSlice(typ, len, cap)

If I want to get the ith value from slice, it's simple:

v := slice.Index(i) // returns a reflect.Value

However, I can't seem to find a way to <i>set</i> the ith value. reflect.Value has lots of setter methods, for example, if I had a map, m, the following is possible:

m.SetMapIndex(key, value) // key and value have type reflect.Value

But there doesn't seem to be an equivalent for slices. My one thought was that maybe the value returned from slice.Index(i) is actually a pointer somehow, so calling v := slice.Index(i); v.Set(newV) would work? I'm not sure. Ideas?

答案1

得分: 25

搞定了!原来我提前发布了这个问题 - 我猜测 slice.Index(0) 返回一个指针是正确的。具体来说:

one := reflect.ValueOf(int(1))

slice := reflect.MakeSlice(reflect.TypeOf([]int{}), 1, 1)
v := slice.Index(0)
fmt.Println(v.Interface())

v.Set(one)
fmt.Println(v.Interface())

v = slice.Index(0)
fmt.Println(v.Interface())

输出结果为:

0
1
1

(这里是在 Go Playground 上的可运行代码)

英文:

Figured it out! Turns out I posted this prematurely - my guess that slice.Index(0) returns a pointer was correct. In particular:

one := reflect.ValueOf(int(1))

slice := reflect.MakeSlice(reflect.TypeOf([]int{}), 1, 1)
v := slice.Index(0)
fmt.Println(v.Interface())

v.Set(one)
fmt.Println(v.Interface())

v = slice.Index(0)
fmt.Println(v.Interface())

prints:

0
1
1

(Here's runnable code on the go playground)

答案2

得分: 1

这可能会有所帮助:

n := val.Len()
if n >= val.Cap() {
    ncap := 2 * n
    if ncap < 4 {
        ncap = 4
    }
    nval := reflect.MakeSlice(val.Type(), n, ncap)
    reflect.Copy(nval, val)
    val.Set(nval)
}
val.SetLen(n + 1)
// ...
val.Index(n).SetString("value") // 取决于类型

这段代码摘自我一段时间前编写的一个库 github.com/webconnex/xmlutil,具体是 decode.go 文件。

英文:

This might help:

n := val.Len()
if n &gt;= val.Cap() {
	ncap := 2 * n
	if ncap &lt; 4 {
		ncap = 4
	}
	nval := reflect.MakeSlice(val.Type(), n, ncap)
	reflect.Copy(nval, val)
	val.Set(nval)
}
val.SetLen(n + 1)
// ...
val.Index(n).SetString(&quot;value&quot;) // Depends on type

Taken from a library I wrote a while back github.com/webconnex/xmlutil, specifically decode.go.

huangapple
  • 本文由 发表于 2013年8月8日 07:59:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/18115785.html
匿名

发表评论

匿名网友

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

确定