Go 範型下,優雅的 Lodash 風

推薦理由

go 語言比較崇尚簡單,所以在內嵌包中沒有提供過多幫助性的函數,尤其在範型出來前想要寫一個簡單的對 slice 和 map 間互相轉化的方法可能就需要很多行代碼,並且這樣並不是很優雅。如今,go 範型已經得到官方的正式發佈,samber/lo 又提供了優雅的 lodash 風格的工具函數,正是代碼重構的好時機。

常見的使用場景

這裏只是用 slice 和 map 兩個常見結構舉個栗子,lo 中支持超多的轉化幫助函數供開發使用。

slice → map

在批量接口中,request 中攜帶 idList ,返回 map response

struct Request {
	IDList []int64
}
struct Response {
	Metas map[int64]Meta
}
// 用於模擬數據庫查詢數據
struct Meta {
	ID int64
	Name string
}
func MGetMeta(req Request) Response{
	result := make([]Meta,0, len(req.IDList))
	// 執行 db query
	db.Raw("select * from meta where id in ?", req.IDList).Scan(&result)
	return Response{
		Metas: MetaResult2Map(result),
	}
}
// 舊代碼: 針對不同的類型需要寫不同的轉化函數
func MetaResult2Map(metas []Meta)map[int64]Meta{
	res := make(map[int64]Meta)
	for _, m := range metas{
		res[m.ID] = m
	}
	return res
}
// 採用 lo:代碼清晰,支持多種結構
func MGetMeta(req Request) Response{
	result := make([]Meta,0, len(req.IDList))
	// 執行 db query
	db.Raw("select * from meta where id in ?", req.IDList).Scan(&result)
	return Response{
		Metas: lo.KeyBy[int64,Meta](a, func(m Meta)int64{
			return m.ID
		}),
	}
}

map → slice

// 在對批量接口接口去重後,可能得到這樣類型參數 map[int64]bool
// 然後在db查詢時其實只用map 的 key 的 slice
// 舊代碼實現
func Int64MapKeys(m map[int64]interface{}) []int64{
	res := make([]int64,0,len(m))
	for k := range m{
		res = append(res, k)
	}
	return res
}
// 使用 lo
lo.Keys[int64,bool](map[int64]bool{1: true,2:true,3:true})
// 批量的聚合接口
// 比如 定時任務中,掃表獲取了一堆數據,分屬於不同的業務方需要分別調用
// 此時參數轉化爲 []T -> map[K][]T ,安裝 T 中的某個字段進行分組
func Group(m []T)map[K][]T{
	res := make(map[K][]T)
	for _, v := range m{
		if _, ok := res[v.Key];ok {
			res[v.Key] = append(res[v.Key],v)
		}else{
			res[v.Key] = []T{v}
		}
	}
	return res
}
// 使用 lo
lo.GroupBy([]Meta{{ID: 1,Name: "1"},{ID: 2, Name: "2"},{ID: 1,Name: "3"}}, func(t Meta) int64 {
		return t.ID
})

總結

samber/lo 使用的開源 MIT 協議中提供了很多轉化數據結構的方法,讓日常開發更加方便優雅,而且其中的代碼並不複雜,全部採用 go1.18 範型標註,對於初學者而言是個學習範型的好地方。筆者就是一邊自己實現,一邊對照 samber/lo 實現學習完這個庫的。

參考

文檔:

https://pkg.go.dev/github.com/samber/lo#KeyBy

github:

https://github.com/samber/lo

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/BFsoQPvrog_sMKMTEofZyQ