创建一个从类型指针到类型的切片。

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

Create a slice of type from a pointer to a type

问题

尝试创建一个切片,其中类型是根据指向特定类型的指针动态设置的,所以我创建了以下示例:

func main() {
    var chicken *Chicken
    // 创建一个鸡的切片
    chickens := GetDynamicTypedSlice(chicken)

    // 这会抛出 "cannot range over chickens (type *[]interface {})" 的错误,我无法弄清楚如何使用上面的鸡指针创建一个切片
    for _, chicken := range chickens {
        fmt.Println(chicken)
    }
}

type Chicken struct {
    Weight float64
}

func GetDynamicTypedSlice(ptrItemType interface{}) *[]interface{} {
    var collection []interface{}
    itemType := reflect.TypeOf(ptrItemType).Elem()
    for i := 0; i < 1000; i++ {
        // 创建所需类型的项
        item := reflect.New(itemType)
        // 为重量值设置一个随机浮点数
        item.Elem().FieldByName("Weight").SetFloat(rnd.ExpFloat64())
        collection = append(collection, &item)
    }
    return &collection
}
  • 我应该怎么做才能在返回的切片上使用 range?
  • 如何将 itemType 用作我的切片的类型?
英文:

Trying to create a slice in which the type is set dynamicaly based on a pointer to a specific type, so i made the following sample

func main() {
	var chicken *Chicken
	//create a slice of chickens
	chickens:=GetaDynamiclyTypedSlice(chicken)
    
	//this throws  cannot range over chickens (type *[]interface {}) and i cant figure how to create a slice using my above chicken pointer
	for _,chicken := range chickens{
		fmt.Println(chicken)
	}

}

type Chicken struct{
	Weight float64
}

func GetaDynamiclyTypedSlice(ptrItemType interface{})*[]interface {}{
	var collection []interface{}
	itemtyp := reflect.TypeOf(ptrItemType).Elem()
	for i:=0;i&lt;1000;i++{
        //create an item of the wanted type
		item := reflect.New(itemtyp)
        //set a random float to the weight value
		item.Elem().FieldByName(&quot;Weight&quot;).SetFloat(rnd.ExpFloat64())
		collection = append(collection,&amp;item)
	}
	return &amp;collection
}
  • what should i do to be able to use range on the returned slice?
  • how can i use the itemtyp as the type of my slice?

答案1

得分: 2

你只需要取消引用指针(这样你就不是在迭代指针,而是在迭代切片):

for _, chicken := range *chickens {
    // ...
}

Playground链接:http://play.golang.org/p/NBv9sooqEV

英文:

You just need to dereference the pointer (so you're not iterating over a pointer - you're iterating over a slice):

for _, chicken := range *chickens {
    // ...
}

Playground link: http://play.golang.org/p/NBv9sooqEV

答案2

得分: 2

你的代码存在几个问题。

  1. 你返回的是一个指向 reflect.Value 的指针,我99%确定这不是你想要实现的。

  2. 你没有像Simon提到的那样对切片进行解引用。

  3. 切片是指针类型,如果出于性能原因你返回的是 *[]interface{},实际上是在阻碍而不是帮助。

所以让我们重写代码并进行优化吧!(现在是深夜,是时候狂欢了):

// 传入大小以预分配切片,并返回正确的切片类型。
func GetaDynamiclyTypedSlice(ptrItemType interface{}, size int) (col []interface{}) {
    col = make([]interface{}, size)
    itemtyp := reflect.TypeOf(ptrItemType).Elem()
    for i := range col { // 比起 for i := 0; etc etc 更加优雅
        item := reflect.New(itemtyp)
        item.Elem().FieldByName("Weight").SetFloat(rand.ExpFloat64())
        col[i] = item.Interface() // 这是关键,返回实际的项,而不是 reflect.Value
    }
    return
}

playground

英文:

There are few problems with your code.

  1. You're returning a pointer to a reflect.Value, 99% sure that's not what you're trying to achive.

  2. You're not dereferencing the slice like Simon mentioned.

  3. Slices are pointer types, if you're returning *[]interface{} for performance reasons, you're actually hurting not helping.

So let's rewrite the code and optimize it! (it's late night SO, time to party):

// pass the size to preallocate the slice, also return the correct slice type.
func GetaDynamiclyTypedSlice(ptrItemType interface{}, size int) (col []interface{}) {
	col = make([]interface{}, size)
	itemtyp := reflect.TypeOf(ptrItemType).Elem()
	for i := range col { //prettier than for i := 0; etc etc
		item := reflect.New(itemtyp)
		item.Elem().FieldByName(&quot;Weight&quot;).SetFloat(rand.ExpFloat64())
		col[i] = item.Interface() //this is the magic word, return the actual item, not reflect.Value
	}
	return
}

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2014年7月22日 09:35:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/24877566.html
匿名

发表评论

匿名网友

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

确定