一、前言

群里的兄弟提问,如果不使用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和指针类型。

file
file

  • 先将表名做适当转换
  • 以转化后的表名做key从modelCache取出模型,如果取出成功则创建QuerySeter,否则会因为表名不存在panic