从指向类型的指针创建类型的切片

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<1000;i++{
        //create an item of the wanted type
        item := reflect.New(itemtyp)
        //set a random float to the weight value
        item.Elem().FieldByName("Weight").SetFloat(rnd.ExpFloat64())
        collection = append(collection,&item)
    }
    return &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?

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("Weight").SetFloat(rand.ExpFloat64())
        col[i] = item.Interface() //this is the magic word, return the actual item, not reflect.Value
    }
    return
}

playground

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