英文:
Reflecting The Fields of a Empty's Slices Underyling Type?
问题
我有以下的查询构建函数:
func CreateQuery(t interface{}, where string) {
var b bytes.Buffer
b.WriteString("SELECT ")
s := reflect.ValueOf(t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField() - 1; i++ {
b.WriteString(fmt.Sprintf("%s, ", typeOfT.Field(i).Name))
}
// 最后一个字段没有逗号
b.WriteString(fmt.Sprintf("%s ", typeOfT.Field(s.NumField() - 1).Name))
b.WriteString(fmt.Sprintf("FROM %s ", typeOfT.Name()))
b.WriteString(where)
fmt.Println(b.String())
}
当以以下方式调用时,它可以正常工作:
var dst FooStruct
CreateQuery(&dst, "")
但是以下代码会引发一个"call of reflect.Value.NumField on slice Value"的错误:
var dst []FooStruct
CreateQuery(&dst, "")
我该如何修改函数以打印切片的底层结构类型的字段?看起来我需要反转reflect的SliceOf函数。
英文:
I have the following query builder function:
func CreateQuery(t interface{}, where string) {
var b bytes.Buffer
b.WriteString("SELECT ")
s := reflect.ValueOf(t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField() - 1; i++ {
b.WriteString(fmt.Sprintf("%s, ", typeOfT.Field(i).Name))
}
//Last one has no Comma
b.WriteString(fmt.Sprintf("%s ", typeOfT.Field(s.NumField() - 1).Name))
b.WriteString(fmt.Sprintf("FROM %s ", typeOfT.Name()))
b.WriteString(where)
fmt.Println(b.String())
}
There works fine when called as follows:
var dst FooStruct
CreateQuery(&dst, "")
But the following raises a "call of reflect.Value.NumField on slice Value" Panic:
var dst []FooStruct
CreateQuery(&dst, "")
How I can I make the function print the fields of a slice's underlying struct type? It seems like I want the inverse of reflect's SliceOf function.
答案1
得分: 3
你只能在表示结构体的reflect.Type上调用NumField或Field方法(即t.Kind() == reflect.Struct)。
如果你有一个切片类型,你可以通过Elem方法访问其中包含的类型,该方法返回另一个reflect.Type。如果切片包含一个结构体,那么你可以在该类型上调用NumField/Field方法。
英文:
You can only call NumField or Field methods on a reflect.Type representing a struct (i.e. t.Kind() == reflect.Struct).
If you have a slice type, you can access the contained type via the Elem method, which returns another reflect.Type. If the slice contains a struct, then you can call NumField/Field on this type.
答案2
得分: 1
你可以遍历切片,在每个查询上调用CreateQuery函数:
func CreateQueries(t interface{}, where string) {
v := reflect.ValueOf(t)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
for i := 0; i < v.Len(); i++ {
CreateQuery(v.Index(i).Interface(), where)
}
}
}
使用reflect.Value.Index可以单独访问每个字段,调用.Interface()方法可以将值转换为interface{}类型的表示,使其适用于放入CreateQuery函数中(该函数期望一个interface{}值)。
英文:
You can iterate over the slice, calling CreateQuery for every query:
func CreateQueries(t interface{}, where string) {
v := reflect.ValueOf(t)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
for i := 0; i < v.Len(); i++ {
CreateQuery(v.Index(i).Interface(), where)
}
}
}
Using reflect.Value.Index you can access each field separately, calling .Interface() on the
value yields the interface{} type representation of that value, making it suitable to put
it in your CreateQuery function (which expects a interface{} value).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论