解決方案在文末
問題引入
今天閑來無事,想要上手一下gorm,但是開始就碰壁了!
明明數據庫都連接成功了,但是...
代碼:
type Account struct {
id int
name string
money float64
}
func main() {
db, err := gorm.Open("mysql", "username:pswd@(127.0.0.1)/db?charset=utf8mb4&parseTime=True&loc=Local")
db.SingularTable(true)
defer db.Close()
if err != nil {
panic("failed to connect database")
}
var account Account
var arr []Account
fmt.Println(db.HasTable(account))
db.Find(&arr)
fmt.Println(arr)
}
運行結果:
true
[{0 0} {0 0} {0 0} {0 0}]
問題分析
我們可以確定的是:
- 數據庫連接成功
- 數據庫也確確實實是有account這張表
- 能查出來我這張表有4條數據,有四個account對象,但就是值放不進去
怎么就查不出來呢???
根據上面可以推測,我們是能找到對應的對象關系的,但是就是值放不進去
俺以前是寫Java的,用過的ORM主要就是MyBatis,我極力的回想,總感覺就差一點點,算了,面向互聯網編程把,於是我去StackOverflow上逛了一下,果真找到了解決的方案!
解決思路
首先明確我們的問題:我們找的到對應的對象,但是!【值】放不進去!
我們知道Go和Java一樣,是靜態語言,要做動態的特性,得靠多態、反射來提供,而我們這邊的gorm框架就是用了【反射】這一技術,找到相對應的數據行,通過類模板創建對象,再將列屬性一個個賦值進去再返回,問題就出在這里!!!
為什么放不進去?因為我把它給封裝了!!!
Go里面,是通過首字母的大小寫來控制封裝,大寫公開,小寫隱藏,而我在Java里小寫習慣了,這里也很自然的小寫了!而Java里我通常為了方便也會用Lombok插件,也就沒怎么寫過getter和setter,我的印象中Java雖然變量隱藏,但可以通過反射來拿出對象的set方法,把值裝進去,但是Go有沒有呢?我的猜測是沒有,因為很多庫里面,也並沒有使用這種方法,所以我的猜測是gorm也不會支持getter和setter這種東西
我們來看看官方的《Effective Go》是怎么說的:
所以,變量被我給隱藏起來了,gorm自然值裝不進去了
解決過程
把首字母改為大寫:
type Account struct {
Id int
Name string
Money float64
}
運行結果:
true
[{1 aaa 500} {2 bbb 1000} {3 ccc 1000} {4 張三 666}]
成了!
坑點
- Go的反射機制
- Go的封裝