最近研究了一下reflect包,感觉这个包的功能很强大,顺便研究了一下如何在函数中动态创建struct{},平常我们都是用如下方式定义struct类型。
type TmpStuct struct {
Height float64 `json:"height"`
Age int `json:"age"`
Test int `json:"test"`
}
这种情况下是我们知道里面的字段和tag属性,我们才能定义好这个结构。如果我们有时候读不同的数据库不同的数据表,事先我们又不确定这些数据表的字段,但是数据表是存在另外一个地方,这个时候我们需要动态创建struct类型来临时建类型,以及设置对应的tag和执行的sql进行绑定,这样才能从数据库把对应的数据表读出来。
下面我们看下如何通过reflect来实现建struct类型。
比如我们要建一个带有Height,Age,Test三个字段的结构。
package main
import (
"fmt"
"reflect"
)
func main() {
tmpStuct := []reflect.StructField{
{
Name: "Height",
Type: reflect.TypeOf(float64(0)),
Tag: `json:"height"`,
},
{
Name: "Age",
Type: reflect.TypeOf(int(0)),
Tag: `json:"age"`,
},
{
Name: "Test",
Type: reflect.TypeOf(int(0)),
Tag: `json:"test"`,
},
}
typ := reflect.StructOf(tmpStuct)
fmt.Printf("%v", typ)
}
上面的代码执行的结果如下:
struct { Height float64 "json:\"height\""; Age int "json:\"age\""; Test int "json:\"test\"" }
上面是动态创建了struct类型,创建这个类型可以用于绑定查询单个sql,查询sql我们很多时候也有批量查询的需求,我们如何把上面的定义的struct又转换成slice呢?我们接下来看下下面的代码
package main
import (
"fmt"
"reflect"
)
func main() {
tmpStuct := []reflect.StructField{
{
Name: "Height",
Type: reflect.TypeOf(float64(0)),
Tag: `json:"height"`,
},
{
Name: "Age",
Type: reflect.TypeOf(int(0)),
Tag: `json:"age"`,
},
{
Name: "Test",
Type: reflect.TypeOf(int(0)),
Tag: `json:"test"`,
},
}
typ := reflect.StructOf(tmpStuct)
fmt.Printf("%v\n", typ)
//下面是把typ转换成[]typ slice结构
tSlice := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0)
tmp := reflect.New(tSlice.Type()).Elem().Addr().Interface()
fmt.Printf("%+v", reflect.TypeOf(tmp).Elem())
}
上面代码执行结果如下:
struct { Height float64 "json:\"height\""; Age int "json:\"age\""; Test int "json:\"test\"" }
[]struct { Height float64 "json:\"height\""; Age int "json:\"age\""; Test int "json:\"test\"" }
slice的创建我们还是通过reflect来实现。通过makeslice函数来处理,这样就能创建这个slice了。
好了,到这里我们就先简单讲完动态创建stuct类型以及当前struct转换成slice的案例。等后面有时候我研究透relect函数,讲讲relect函数的原理实现。