英文:
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<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?
答案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
你的代码存在几个问题。
-
你返回的是一个指向
reflect.Value
的指针,我99%确定这不是你想要实现的。 -
你没有像Simon提到的那样对切片进行解引用。
-
切片是指针类型,如果出于性能原因你返回的是
*[]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
}
英文:
There are few problems with your code.
-
You're returning a pointer to a
reflect.Value
, 99% sure that's not what you're trying to achive. -
You're not dereferencing the slice like Simon mentioned.
-
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论