在使用 orm 操作数据的过程中,gorm 使用 struct 对数据库中的表进行定位。虽然虽然可以 一个表定义一套 增删查改 但是感觉需要的代码量比较多。所以我决定通过字符串访问结构体已应对简单的 增删查改。
这里简单的介绍一下原理新建一个 map ,key 为我们使用的字符串 value 为反射类型,在使用的时候从 map 中取出值,然后通过反射新建出需要使用的类型
这里我先简单声明一下,然后在对它进行封装,以方便我们之后的使用
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Test struct { // 我们需要使用到的结构体
Name string `json:"name"`
}
func main() {
temp := make(map[string]reflect.Type) // 建立一个类似于模板仓库的东西
temp["test"] = reflect.TypeOf(Test{}) // 将类型转换成反射类型在需要使用的时候通过反射新建对应实例
// 上面是如何存储
//-----------------------
// 接下来就是如何取出来了
t, ok := temp["test"] // 检查元素是否真实存在
if !ok {
panic("test 结构体未进行储存") // 这里只是演示实际处理根据你的真实使用情况来定
}
fmt.Printf("%T\n", t) // 检查一下类型司机上并没有哦什么用
// 通过反射新建实例并转成 interface 别问我为什么这样写 如果放进去的是一个 对应类型的 interface 再反射出来使用,在第二次使用时携带上一次的值(不是本次使用的方式)
foo := reflect.New(t).Interface() // 类似于 new(type) 因为下一步会使用反射将值放进去
fmt.Printf("%T\n", foo) // 检测一下即将使用的类型
// 类型新建好后对它进行赋值
// 使用 json 解析将值放进去当然你也可以使用反射 不过我觉得这种方式更简单
m := map[string]interface{}{"name": "niconiconi"}
res, err := json.Marshal(m)
if err != nil {
panic(err)
}
if err := json.Unmarshal(res, foo); err != nil {
panic(err)
}
fmt.Printf("type == %T | value == %v\n", foo, foo) // 检测一下类型以及值
// 到这里就结束了
}
在上面了例子中演示了,如何通过 string 访问 struct 当然在实际使用中是可能会有多个 model 需要使用我们都把它塞进 map 就好了。
为了方便使用我们可以对上面的例子加一点点细节,类似于下面这样
// 在使用之前 调用 New 函数新建工厂
// Add 方法 放入你需要的类型
// Get("typeName") 获取你需要的类型
package factory
import (
"fmt"
"reflect"
"strings"
)
// Store 模板实体
type Store struct {
temp map[string]reflect.Type
}
// Add 添加(需要 非指针)
func (m *Store) Add(in ...interface{}) {
if m.temp == nil {
m.temp = make(map[string]reflect.Type)
}
for _, v := range in {
refType := reflect.TypeOf(v)
split := strings.Split(refType.String(), ".")
name := strings.ToLower(split[len(split)-1])
m.temp[name] = refType
}
}
// Get 获取一个新的模板(指针类型)
func (m Store) Get(name string) (interface{}, error) {
layout, ok := m.temp[name]
if !ok {
return nil, fmt.Errorf("%s does not exist", name)
}
temp := reflect.New(layout).Interface()
return temp, nil
}
// New 新建
func New() Store {
return Store{}
}
使用方式类似于下面这样,注意不是真实代码
package main
var prop = factory.New()
func init() {
prop.Add(user{}, file{})
}
func foo() (interface{}, int46 ,error) {
tableS := "user" // 外部获取
rows, err := prop.Get(tableS)
if err != nil{
return, 0, err
}
// 然后使用上面例子中 json 的方式放进去 或者 给其他 组件使用
//err = db.X().Model(local).Where(kvs).Count(&total).Order(sort).Offset((pi - 1) * ps).Limit(ps).Find(rows).Error
//return rows, total, err
}
在这里提供一个 gorm 的查询思路 表 从 uri 中获取 查询条件 使用 url ? 后面的 字符串(也叫查询条件)并将其转换成 map 塞进 gorm 的查询条件结果映射回我们 上面封装的方法获取的模板。
需要一个 我们就放一个 struct 需要 []struct 那就放 []struct 进去 全程不需要一条 SQL 语句 真香。
最后祝你玩得开心 (*^_^*)