反映基础类型的空切片的字段?

时间:2013-12-10 14:04:08

标签: reflection go

我有以下查询构建器功能:

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())
}

按以下方式调用时效果很好:

var dst FooStruct
CreateQuery(&dst, "")

但以下提出了“对slice.Value.NumField on slice Value”的调用恐慌:

var dst []FooStruct
CreateQuery(&dst, "")

如何让函数打印切片底层结构类型的字段?看起来我想要反映的SliceOf函数的反转。

2 个答案:

答案 0 :(得分:3)

您只能在代表结构的NumField上调用Fieldreflect.Type种方法(即t.Kind() == reflect.Struct)。

如果您有切片类型,则可以通过Elem方法访问包含的类型,该方法将返回另一个reflect.Type。如果切片包含结构,那么您可以在此类型上调用NumField / Field

答案 1 :(得分: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() value产生该值的interface{}类型表示,使其适合放置 它位于CreateQuery函数中(需要interface{}值)。