reflect.Set slice-of-structs value to a struct, without type assertion (because it's unknown)

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

reflect.Set slice-of-structs value to a struct, without type assertion (because it's unknown)

问题

我正在创建一个辅助包,用于从队列中弹出有效载荷。这个辅助包对导入它的应用程序使用的结构类型是不可知的,这一点非常重要。

下面是一个示例函数(无操作),它将从队列中提供一个指定类型的有效载荷,类型为interface{}

func One(like interface{}) interface{} {
    typ := reflect.TypeOf(like)
    one := reflect.New(typ)
    
    return one.Interface()
}

下面的函数提供多个有效载荷:

func Many(num int, like interface{}) interface{} {
    typ := reflect.TypeOf(like)
    many := reflect.MakeSlice(reflect.SliceOf(typ), num, num)

    for i := 0; i < num; i++ {
        one := One(typ)
        many.Index(i).Set(one)
    }

    return many.Interface()
}

以下是用法示例:

type Payload struct {
    Id   int
    Text string
}

func main() {
    Many(4, Payload{})
}

然而,上述代码会导致以下错误:

panic: reflect.Set: value of type **reflect.rtype is not assignable to type main.Payload

你可以在这里查看完整的示例代码:https://play.golang.org/p/ud23ZlD3Bx

英文:

I'm creating a helper package to pop payloads from a queue. It's essential that this helper be agnostic to the struct used by the application importing it.

This (no-op, just example) function will provide a single payload from the queue, of the provided type like interface{}:

func One(like interface{}) interface{} {
	typ := reflect.TypeOf(like)
	one := reflect.New(typ)
	
	return one.Interface()
}

This function provides many payloads:

func Many(num int, like interface{}) interface{} {
	typ := reflect.TypeOf(like)
	many := reflect.MakeSlice(reflect.SliceOf(typ), num, num)

	for i := 0; i &lt; num; i++ {
		one := One(typ)
		many.Index(i).Set(one)
	}

	return many.Interface()
}

An example of usage is:

type Payload struct {
    Id int
    Text string
}

func main() {
    Many(4, Payload{})
}

However, the above results in:

panic: reflect.Set: value of type **reflect.rtype is not assignable to type main.Payload

https://play.golang.org/p/ud23ZlD3Bx

答案1

得分: 2

你正在对reflect.Value调用reflect.TypeOf,这就是**reflect.rtype的来源。

直接使用like值调用你的One函数,并将结果赋给切片。

func One(like interface{}) interface{} {
    typ := reflect.TypeOf(like)
    one := reflect.New(typ)

    return one.Interface()
}

func Many(num int, like interface{}) interface{} {
    typ := reflect.TypeOf(like)
    many := reflect.MakeSlice(reflect.SliceOf(typ), num, num)

    for i := 0; i < num; i++ {
        one := One(like)
        many.Index(i).Set(reflect.ValueOf(one).Elem())
    }

    return many.Interface()
}

https://play.golang.org/p/fHF_zrymcI

英文:

You're calling reflect.TypeOf on a reflect.Value, which is where **reflect.rtype is coming from.

Call your One function wth the like value directly, and assign that result to the slice.

func One(like interface{}) interface{} {
	typ := reflect.TypeOf(like)
	one := reflect.New(typ)

	return one.Interface()
}

func Many(num int, like interface{}) interface{} {
	typ := reflect.TypeOf(like)
	many := reflect.MakeSlice(reflect.SliceOf(typ), num, num)

	for i := 0; i &lt; num; i++ {
		one := One(like)
		many.Index(i).Set(reflect.ValueOf(one).Elem())
	}

	return many.Interface()
}

https://play.golang.org/p/fHF_zrymcI

huangapple
  • 本文由 发表于 2016年11月8日 05:10:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/40474682.html
匿名

发表评论

匿名网友

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

确定