GoFrame代碼優化gconv類型轉換避免重復定義map

前言

最近一直在研究 GoFrame 框架,經過一段時間的使用、總結、思考,發現確實不失為一款非常值得使用的企業級開發框架。

在我初識GoFrame教程後,曾整理過一篇文章: 非常適合PHP同學學習的GO框架:GoFrame,有興趣的同學可以閱讀一下。

今天重點講一下我使用GoFrame的代碼優化之旅。

核心重點

GoFrame幾乎封裝瞭所有能封裝的東西,而我們需要做的就是在框架的基礎上約定好自己項目的開發規范。

一定要遵守統一的規范!

一定要遵守統一的規范!

一定要遵守統一的規范!

類型轉換:GoFrame框架提供瞭非常強大易用的類型轉換包gconv,可以實現將常用數據類型轉換為指定的數據類型,對常用基本數據類型之間的無縫轉換,同時也支持任意類型到struct對象的轉換。由於gconv模塊內部大量優先使用瞭斷言而非反射,因此執行的效率非常高。

數據庫ORM:通過Scan方法自動識別Map/Struct接收查詢結果,自動化查詢結果初始化、結構體類型轉換; 完美支持GoFrame框架層面的DAO設計,全自動化Model/DAO代碼生成,極大提高開發效率。

以上兩個部分是重中之重,建議大傢好好研究。

類型轉換 和 數據庫ORM 也是我下面優化代碼的重要參考。

優化前

//獲取商品類目接口
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
}

這種重復定義讓我很難受:

categoryMapping := map[string]interface{}{
		"level":       level,
		"code":        code,
		"name":        name,
		"parent_code": parent_code,
	}

優化後:

去掉定義map:

//獲取商品類目接口
func (s *goMeGoodsService) GetCategory(pid ...interface{}) {
	ctx := context.Background()
	res, err := gome.Category.Get(ctx, pid)
	if err != nil {
		checkErr(err, "GetCategory AddCategory")
	}
        //循環單條插入
        for _, v := range res.Data {
         _, err := dao.GomeCategory.Data(v).Insert()
         if err != nil {
            checkErrGome(err, "db添加分類失敗")
         }
        }
}

可以這麼寫的原因

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結構體:

type CategoryRes struct {
	*CommonRes
	Data []struct {
		Code       string `json:"code"`
		Level      int    `json:"level"`
		ParentCode string `json:"parentCode"`
		Name       string `json:"name"`
	} `json:"data"`
}

進一步優化 批量寫入

CategoryRes.Data 就是需要入庫的數組,我們直接使用Data()函數賦值,進行批量插入就行瞭。(默認每次插入10條數據,可以通過batch(x)指定每次插入的數據條數)

dao.GomeCategory.Data(res.Data).Insert()

更優雅的寫法如下

//獲取商品類目接口
func (s *goMeGoodsService) GetCategory() {
	ctx := context.Background()
	//一級類名
	res, err := gome.Category.Get(ctx)
	if err != nil {
		checkErr(err, "GetCategory AddCategory")
	}
	//批量插入 優雅
	_, batchErr := dao.GomeCategory.Data(res.Data).Insert()
	if batchErr != nil {
		checkErr(batchErr, "批量更新一級目錄失敗")
	}
}

可以向上滑,看看優化前的代碼是怎麼寫的。

優化後的代碼完全實現瞭優化代碼前的功能,且性能更好,因為使用瞭批量插入。

總結

避免這種重復定義map的代碼, 合理使用gconv對map、結構體、結構體數組進行轉換。

不要像下面這樣寫代碼!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
}

要有這種優化代碼的意識,當我們意識到重復定義時,就一定有辦法優化。

當我們意識到邏輯混亂時,就一定有辦法優化結構,混亂的邏輯往往是設計的不合理導致的。

以上就是GoFrame代碼優化gconv類型轉換避免重復定義map的詳細內容,更多關於GoFrame gconv類型轉換的資料請關註WalkonNet其它相關文章!

推薦閱讀: