blog
blog copied to clipboard
动手写ORM框架 - GeeORM第二天 对象表结构映射 | 极客兔兔
https://geektutu.com/post/geeorm-day2.html
7天用 Go语言/golang 从零实现 ORM 框架 GeeORM 教程(7 days implement golang object relational mapping framework from scratch tutorial),动手写 ORM 框架,参照 gorm, xorm 的实现。使用反射(reflect)获取任意 struct 对象的名称和字段,映射为数据中的表;使用 dialect 隔离不同数据库之间的差异,便于扩展;数据库表的创建(create)、删除(drop)。
你好,我想问一下 var _ Dialect = (*sqlite3)(nil) 这一步的作用是什么呢?
Dialect 方言---用来处理不同数据库的类型 这个名字取的值得学习
func (s *sqlite3) DataTypeOf(typ reflect.Value) string
这个函数里** typ **的类型可以为reflect.Vaule,reflect.Type甚至是reflect.StructField。请教下如果不是为了利用反射修改值这种情况,其他几种方式是不是都可以任意使用?
最终如果Model的参数是传指针的话 那应该是只能用reflect.Value类型了
DataTypeOf(typ reflect.Type) string
是否更加简洁?
Type: d.DataTypeOf(p.Type)
DataTypeOf 应该不需要关心 Value 是什么。判断是不是 time.Time 似乎也可以使用:
if typ.ConvertibleTo(reflect.TypeOf(time.Time{})) {
return "datetime"
}
@walkmiao 传不传指针不影响可读性吧?
Model()传指针有什么好处呢 我传的对象结构体也没有什么 这样做的好处在哪呢 仅仅是节约内存传指针的吗
var _ Dialect = (*sqlite3)(nil) 这种写法与go的版本有关系吗,写了以后编译器报错,执行也报错,说没有实现另一个方法
@walkmiao Model 不修改原数据,所以传指针只是为了节省空间。而且对于复杂结构体来说,传结构体,也只是浅拷贝,意义也不大。
@ayuayue 静态检查用的,参考 类似var _ PeerPicker = (*HTTPPool)(nil)这种设计目的是什么
大佬不去培训机构当老师的话就太可惜了
table_test.go中的NewSession(),为什么不创建Engine实例就可以调用呢?我这边一直报红。
@BrianQy table_test.go中的NewSession(),为什么不创建Engine实例就可以调用呢?我这边一直报红。
加入在raw_test.go
中的两段代码就行了:
var (
TestDB *sql.DB
TestDial, _ = dialect.GetDialect("sqlite3")
)
func TestMain(m *testing.M) {
TestDB, _ = sql.Open("sqlite3", "../gee.db")
code := m.Run()
_ = TestDB.Close()
os.Exit(code)
}
func NewSession() *Session {
return New(TestDB, TestDial)
}
纠错:dialect 目录下新建文件 sqlite3.go时,应该在import里写上:_ "github.com/mattn/go-sqlite3" 来执行sqlite3的驱动的初始化,这样以后用到sqlite3时,只要导入dialect就自己执行了sqlite3的驱动的初始化,不用再写一遍import _ "github.com/mattn/go-sqlite3"(如果不写这个import就会使sql.Open失败)
@Alex-Jee 纠错:dialect 目录下新建文件 sqlite3.go时,应该在import里写上:_ "github.com/mattn/go-sqlite3" 来执行sqlite3的驱动的初始化,这样以后用到sqlite3时,只要导入dialect就自己执行了sqlite3的驱动的初始化,不用再写一遍import _ "github.com/mattn/go-sqlite3"(如果不写这个import就会使sql.Open失败)
交给使用者调用会更明了些
请问Parse()函数中为什么不用reflect的Elem()函数而用Indirect()函数呢
@niconical 请问Parse()函数中为什么不用reflect的Elem()函数而用Indirect()函数呢
传入的类型为Interface,此时可以传入地址也可以传入结构体,如果采用Elem函数在对于传入结构体的情况下会发生Panic,而Indirect则可以正常执行
@niconical 请问Parse()函数中为什么不用reflect的Elem()函数而用Indirect()函数呢
Indirect返回v指向的值,如果v是个nil指针,Indirect返回0值,如果v不是指针,Indirect返回v本身。这里也理解了为啥要起Indirect这个名字,间接获取到了v指向的值. 这样可以兼容 结构体和指针的情况