当前位置: 首页 > 工具软件 > beedb > 使用案例 >

阅读谢大的beedb,学习Go语言的反射机制

公良向阳
2023-12-01
func (orm *Model) ScanPK(output interface{}) *Model {
    if reflect.TypeOf(reflect.Indirect(reflect.ValueOf(output)).Interface()).Kind() == reflect.Slice {
        sliceValue := reflect.Indirect(reflect.ValueOf(output))
        sliceElementType := sliceValue.Type().Elem()
        for i := 0; i < sliceElementType.NumField(); i++ {
            bb := sliceElementType.Field(i).Tag
            if bb.Get("beedb") == "PK" || reflect.ValueOf(bb).String() == "PK" {
                orm.PrimaryKey = sliceElementType.Field(i).Name
            }
        }
    } else {
        tt := reflect.TypeOf(reflect.Indirect(reflect.ValueOf(output)).Interface())
        for i := 0; i < tt.NumField(); i++ {
            bb := tt.Field(i).Tag
            if bb.Get("beedb") == "PK" || reflect.ValueOf(bb).String() == "PK" {
                orm.PrimaryKey = tt.Field(i).Name
            }
        }
    }
    return orm

}
开始看谢大的beedb,结果在Model.ScanPk(interface{})就卡住了,主要是对函数中一些反射相关的API不了解,那就从反射开始研究吧。

先来介绍ScanPK中会涉及到的几个数据结构,这里只会写到跟这个函数相关的数据结构的相关字段,如果有兴趣进一步研究的话请移步golang reflect

  • Type 表示数据结构类型的数据结构,部分字段的声明如下:
type Type interface {

        // 这个Type的种类
        Kind() Kind

        // 查找这个Type的第 i 个字段
        Field(i int) StructField

        // 字段的数量
        NumField() int
}
  • Value 表示数据结构值的数据结构,部分字段的声明如下:

  • Kind Go语言内置类型的枚举值,声明如下:

    const (
            Invalid Kind = iota
            Bool
            Int
            Int8
            Int16
            Int32
            Int64
            Uint
            Uint8
            Uint16
            Uint32
            Uint64
            Uintptr
            Float32
            Float64
            Complex64
            Complex128
            Array
            Chan
            Func
            Interface
            Map
            Ptr
            Slice
            String
            Struct
            UnsafePointer
    )


  • StructField 用于描述一个数据结构的字段,部分字段声明如下:
type StructField struct {
        // 这个字段的名字
        Name    string

        Tag       StructTag // 这个字段的注释
}


  • StructTag StructField中有一个Tag字段,这个字段是对所属字段属性的一种补充。比如现在有一个自定义的数据结构声明如下:
type Person struct {
    Name string `json:"name"`
    Age int
}


与C语言不同的地方是,Name字段在声明后,又添加了一段被反引号(`)包围的字符串,这个字符串的规则是键名:"值"。那么这种类型的结构在被反射时,这段被包围的字符串便会被解析到StructTag中,可以使用函数StructTag.Get(key string)来获得某个值。

到这里,需要用到的数据结构就都交代完毕了,其中最重要的两个数据结构是Value、Type,一个表示值,一个表示类型。接下来再看几个函数。

 类似资料: