GoFrame代碼優(yōu)化gconv類型轉(zhuǎn)換避免重復(fù)定義map
前言
最近一直在研究 GoFrame 框架,經(jīng)過(guò)一段時(shí)間的使用、總結(jié)、思考,發(fā)現(xiàn)確實(shí)不失為一款非常值得使用的企業(yè)級(jí)開(kāi)發(fā)框架。
在我初識(shí)GoFrame教程后,曾整理過(guò)一篇文章: 非常適合PHP同學(xué)學(xué)習(xí)的GO框架:GoFrame,有興趣的同學(xué)可以閱讀一下。
今天重點(diǎn)講一下我使用GoFrame的代碼優(yōu)化之旅。
核心重點(diǎn)
GoFrame幾乎封裝了所有能封裝的東西,而我們需要做的就是在框架的基礎(chǔ)上約定好自己項(xiàng)目的開(kāi)發(fā)規(guī)范。
一定要遵守統(tǒng)一的規(guī)范!
一定要遵守統(tǒng)一的規(guī)范!
一定要遵守統(tǒng)一的規(guī)范!
類型轉(zhuǎn)換:GoFrame
框架提供了非常強(qiáng)大易用的類型轉(zhuǎn)換包gconv
,可以實(shí)現(xiàn)將常用數(shù)據(jù)類型轉(zhuǎn)換為指定的數(shù)據(jù)類型,對(duì)常用基本數(shù)據(jù)類型之間的無(wú)縫轉(zhuǎn)換,同時(shí)也支持任意類型到struct
對(duì)象的轉(zhuǎn)換。由于gconv
模塊內(nèi)部大量?jī)?yōu)先使用了斷言而非反射,因此執(zhí)行的效率非常高。
數(shù)據(jù)庫(kù)ORM:通過(guò)Scan
方法自動(dòng)識(shí)別Map/Struct
接收查詢結(jié)果,自動(dòng)化查詢結(jié)果初始化、結(jié)構(gòu)體類型轉(zhuǎn)換; 完美支持GoFrame
框架層面的DAO
設(shè)計(jì),全自動(dòng)化Model/DAO
代碼生成,極大提高開(kāi)發(fā)效率。
以上兩個(gè)部分是重中之重,建議大家好好研究。
類型轉(zhuǎn)換 和 數(shù)據(jù)庫(kù)ORM 也是我下面優(yōu)化代碼的重要參考。
優(yōu)化前
//獲取商品類目接口 func (s *goMeGoodsService) GetCategory(pid ...interface{}) { ctx := context.Background() res, err := gome.Category.Get(ctx, pid) if err != nil { checkErr(err, "GetCategory AddCategory") } data := res.Data for _, v := range data { if v.Code != "" && v.Name != "" { _, err = s.AddCategory(v.Level, v.Code, v.Name, v.ParentCode) checkErr(err, "GetCategory AddCategory") } } } //添加分類 func (s *goMeGoodsService) AddCategory(level int, code, name, parent_code string) (id int64, err error) { categoryMapping := map[string]interface{}{ "level": level, "code": code, "name": name, "parent_code": parent_code, } sqlRes, err := dao.GomeCategory.Data(categoryMapping).Insert() if err != nil { return } id, err = sqlRes.RowsAffected() if err != nil { return } return }
這種重復(fù)定義讓我很難受:
categoryMapping := map[string]interface{}{ "level": level, "code": code, "name": name, "parent_code": parent_code, }
優(yōu)化后:
去掉定義map:
//獲取商品類目接口 func (s *goMeGoodsService) GetCategory(pid ...interface{}) { ctx := context.Background() res, err := gome.Category.Get(ctx, pid) if err != nil { checkErr(err, "GetCategory AddCategory") } //循環(huán)單條插入 for _, v := range res.Data { _, err := dao.GomeCategory.Data(v).Insert() if err != nil { checkErrGome(err, "db添加分類失敗") } } }
可以這么寫(xiě)的原因
func (categoryGome) Get(ctx context.Context, pid ...interface{}) (res *CategoryRes, err error) { method := "alemein.basic.get.category" req := g.Map{} if len(pid) > 0 { req["parentCode"] = pid[0] } result, err := server.requestApi(ctx, method, req) if err != nil { return } _ = gjson.New(result).Scan(&res) return }
gome.Category.Get(ctx, pid) 返回的是 CategoryRes結(jié)構(gòu)體:
type CategoryRes struct { *CommonRes Data []struct { Code string `json:"code"` Level int `json:"level"` ParentCode string `json:"parentCode"` Name string `json:"name"` } `json:"data"` }
進(jìn)一步優(yōu)化 批量寫(xiě)入
CategoryRes.Data 就是需要入庫(kù)的數(shù)組,我們直接使用Data()
函數(shù)賦值,進(jìn)行批量插入就行了。(默認(rèn)每次插入10條數(shù)據(jù),可以通過(guò)batch(x)指定每次插入的數(shù)據(jù)條數(shù))
dao.GomeCategory.Data(res.Data).Insert()
更優(yōu)雅的寫(xiě)法如下
//獲取商品類目接口 func (s *goMeGoodsService) GetCategory() { ctx := context.Background() //一級(jí)類名 res, err := gome.Category.Get(ctx) if err != nil { checkErr(err, "GetCategory AddCategory") } //批量插入 優(yōu)雅 _, batchErr := dao.GomeCategory.Data(res.Data).Insert() if batchErr != nil { checkErr(batchErr, "批量更新一級(jí)目錄失敗") } }
可以向上滑,看看優(yōu)化前的代碼是怎么寫(xiě)的。
優(yōu)化后的代碼完全實(shí)現(xiàn)了優(yōu)化代碼前的功能,且性能更好,因?yàn)槭褂昧伺坎迦搿?/p>
總結(jié)
避免這種重復(fù)定義map的代碼, 合理使用gconv
對(duì)map、結(jié)構(gòu)體、結(jié)構(gòu)體數(shù)組進(jìn)行轉(zhuǎn)換。
不要像下面這樣寫(xiě)代碼!NO!
//添加分類 func (s *goMeGoodsService) AddCategory(level int, code, name, parent_code string) (id int64, err error) { categoryMapping := map[string]interface{}{ "level": level, "code": code, "name": name, "parent_code": parent_code, } sqlRes, err := dao.GomeCategory.Data(categoryMapping).Insert() if err != nil { return } id, err = sqlRes.RowsAffected() if err != nil { return } return }
要有這種優(yōu)化代碼的意識(shí),當(dāng)我們意識(shí)到重復(fù)定義時(shí),就一定有辦法優(yōu)化。
當(dāng)我們意識(shí)到邏輯混亂時(shí),就一定有辦法優(yōu)化結(jié)構(gòu),混亂的邏輯往往是設(shè)計(jì)的不合理導(dǎo)致的。
以上就是GoFrame代碼優(yōu)化gconv類型轉(zhuǎn)換避免重復(fù)定義map的詳細(xì)內(nèi)容,更多關(guān)于GoFrame gconv類型轉(zhuǎn)換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go如何實(shí)現(xiàn)HTTP請(qǐng)求限流示例
本篇文章主要介紹了Go如何實(shí)現(xiàn)HTTP請(qǐng)求限流示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04深入了解Go的HttpClient超時(shí)機(jī)制
在寫(xiě)?Go?的過(guò)程中經(jīng)常對(duì)比這Java和GO語(yǔ)言的特性,踩了不少坑,也發(fā)現(xiàn)了不少有意思的地方,今天就來(lái)聊聊?Go?自帶的?HttpClient?的超時(shí)機(jī)制2022-11-11詳解Go語(yǔ)言中結(jié)構(gòu)體與JSON間的轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中結(jié)構(gòu)體與JSON間的轉(zhuǎn)換,文中的示例代碼講解詳細(xì),對(duì)學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下2022-12-12Go語(yǔ)言中零拷貝的原理與實(shí)現(xiàn)詳解
零拷貝是相對(duì)于用戶態(tài)來(lái)講的,即數(shù)據(jù)在用戶態(tài)不發(fā)生任何拷貝,那么零拷貝的原理是什么,又是如何實(shí)現(xiàn)的呢,下面小編就來(lái)和大家詳細(xì)聊聊吧2023-08-08GoLang channel底層代碼實(shí)現(xiàn)詳解
Channel和goroutine的結(jié)合是Go并發(fā)編程的大殺器。而Channel的實(shí)際應(yīng)用也經(jīng)常讓人眼前一亮,通過(guò)與select,cancel,timer等結(jié)合,它能實(shí)現(xiàn)各種各樣的功能。接下來(lái),我們就要梳理一下GoLang channel底層代碼實(shí)現(xiàn)2022-10-10