一、前言
群里的兄弟提问,如果不使用beego/orm(下文使用orm代替)自动建表功能,能否使用orm的功能,答案肯定是可以的。接着这位兄弟发上来报错代码:
panic: <Ormer.QueryTable> table name: `treasury` not exists
goroutine 1 [running]:
github.com/astaxie/beego/orm.(*orm).QueryTable(0xc000004540, 0x75bb00, 0x8032a0, 0x661758, 0x7b7bbd)
E:/Workspace/GoProject/src/github.com/astaxie/beego/orm/orm.go:436 +0x33d
main.main()
e:/Workspace/GoProject/project/test/orm_test/main.go:25 +0x94
exit status 2
接下来就是一阵讨论:
:没表
:确定是同一个库吗
:大小写一样吗
:字段名
:感觉像是MySQL驱动不支持
二、解决办法
为了复现上述问题,我写了一段简单的测试代码
package main
import (
"log"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
type Treasury struct {
Id int
Title string
Amount string
}
func init() {
orm.RegisterDataBase("default", "mysql", "xxx:xxx@tcp(localhost:3307)/test?charset=utf8")
}
func main() {
o := orm.NewOrm()
var treasuries []Treasury
o.QueryTable("treasury").All(&treasuries)
log.Println(treasuries)
}
果不其然确实报panic: <Ormer.QueryTable> table name: `treasury` not exists
,对照官方文档,发现初始化数据库是少了注册模型的操作orm.RegisterModel(new(Treasury)),加上后正常了。
package main
import (
"log"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
type Treasury struct {
Id int
Title string
Amount string
}
func init() {
orm.RegisterModel(new(Treasury))
orm.RegisterDataBase("default", "mysql", "xxx:xxx@tcp(localhost:3307)/test?charset=utf8")
}
func main() {
o := orm.NewOrm()
var treasuries []Treasury
o.QueryTable("treasury").All(&treasuries)
log.Println(treasuries)
}
三、寻根问底
在https://github.com/astaxie/beego/blob/develop/orm/orm.go#L422-L442中可以看到,QueryTable接收interface{}类型的参数,通过代码逻辑和注释可以看到,支持string和指针类型。
- 先将表名做适当转换
- 以转化后的表名做key从modelCache取出模型,如果取出成功则创建QuerySeter,否则会因为表名不存在panic