這幾天golang社區(qū)對泛型的討論非常多的,一片熱火朝天的景象。對我們廣大gopher來說總歸是好事。
成都創(chuàng)新互聯(lián)IDC提供業(yè)務:服務器托管,成都服務器租用,服務器托管,重慶服務器租用等四川省內主機托管與主機租用業(yè)務;數據中心含:雙線機房,BGP機房,電信機房,移動機房,聯(lián)通機房。
泛型很有可能會顛覆我們之前的很多設計,帶著這種疑問和沖動,我準備嘗試用golang泛型實現(xiàn)幾個orm的常見功能。
本文并沒完全實現(xiàn)通用的orm,只是探討其實現(xiàn)的一種方式提供各位讀者做借鑒。
雖然golang有了泛型,但是目前在標準庫sql底層還沒有改造,目前還有很多地方需要用到reflect。
調用方式
這個部分跟傳統(tǒng)的orm使用上沒有太大區(qū)別,沒辦法不使用反射的情況下,泛型的方式可能變得有點繁瑣。
調用方式
和創(chuàng)建table類似,寫入數據好像比沒有之前的orm有優(yōu)勢。
讀取數據是非常高頻的操作,所以我們稍作封裝。
調用方式
稍微比原先的orm方式有了多一點想象空間,比如 在[T any]做更明確的約束,比如要求實現(xiàn)Filter定制方法。
鑒于本人能力還認證有限,目前還沒有發(fā)現(xiàn)泛型對orm劇烈的改進和突破的可能。未來如果go對底層sql做出改動,或者實現(xiàn)諸如Rust那種Enum方式,可能會帶來更多的驚喜。
首先spring自帶了mongodb的orm,spring data mongodb,但是這個框架非常難用,最令人抓狂的是每個文檔都要帶一個 _class 字段,因為這個是string的,所以占用不少空間,而且去除也比較麻煩。
在這里我推薦一下基于MongoDB官方提供的orm的輕量級封裝的 zfoo orm 框架 ,只對官方提供的進行了簡單的封裝,還做了一些官方不支持的語法校驗。
models.go
============================
package main
import (
"github.com/astaxie/beego/orm"
)
type User struct {
Id int
Name string
Profile *Profile `orm:"rel(one)"` // OneToOne relation
}
type Profile struct {
Id int
Age int16
User *User `orm:"reverse(one)"` // 設置反向關系(可選)
}
func init() {
// 需要在init中注冊定義的model
orm.RegisterModel(new(User), new(Profile))
}
main.go
==============
package main
import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
//orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "ta3:ta3@/ta3?charset=utf8")
orm.RunSyncdb("default", false, true) // true 改成false,如果表存在則會給出提示,如果改成false則不會提示 , 這句話沒有會報主鍵不存在的錯誤
}
func main() {
o := orm.NewOrm()
o.Using("default") // 默認使用 default,你可以指定為其他數據庫
user := User{Id: 1}
err := o.Read(user)
if err == orm.ErrNoRows {
fmt.Println("查詢不到")
} else if err == orm.ErrMissPK {
fmt.Println("找不到主鍵")
} else {
fmt.Println(user.Id, user.Name)
}
}
執(zhí)行結果:
create table `user`
-- --------------------------------------------------
-- Table Structure for `main.User`
-- --------------------------------------------------
CREATE TABLE IF NOT EXISTS `user` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(255) NOT NULL,
`profile_id` integer NOT NULL UNIQUE
) ENGINE=InnoDB;
create table `profile`
-- --------------------------------------------------
-- Table Structure for `main.Profile`
-- --------------------------------------------------
CREATE TABLE IF NOT EXISTS `profile` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`age` smallint NOT NULL
) ENGINE=InnoDB;
查詢不到
第二次再執(zhí)行:
table `user` already exists, skip
table `profile` already exists, skip
查詢不到
如果 orm.RunSyncdb("default", false, true)改成 orm.RunSyncdb("default", false, false)
則執(zhí)行結果不會提示。
話說,框架不是給一個人用的,是給一個團隊用的。讓大家都保持同一種代碼結構。
以上只是說各大php框架。golang這種追求性能的語言是否需要一個框架仍然是個未知數。我所見過的大部分go類庫的實現(xiàn)還是挺簡單的。golang本身語法支持也比較簡單。
之前用 beego 中自帶的 orm,感覺有一些不是很滿足需求的地方,而且想要嘗試一些新的 orm,寫一篇記錄一下。
在 xorm 和 gorm 之間對比了一下:
p.s. 需要說明的是,對比非常初級,而且項目處于很早期,也抱著嘗試一下不行再改的心理,并沒有想要得到一個孰優(yōu)孰劣的結論。
想來想去,對于一個成熟的項目可能 gorm 更適合,但是 xorm 好像近期在頻繁 commit,有一種想要追趕的意思。
那我先試試 xorm ,不知道為什么選的這個,可能是想試試看新款吧。(大霧
2017/07/04
可怕,xorm 不支持外鍵關系。一對一啥的。