3 回答

TA貢獻(xiàn)1853條經(jīng)驗(yàn) 獲得超6個(gè)贊
不,Go 沒(méi)有泛型并且在可預(yù)見(jiàn)的未來(lái)不會(huì)有它們1。
您有三個(gè)選擇:
重構(gòu)您的代碼,以便您擁有一個(gè)接受 SQL 語(yǔ)句和另一個(gè)函數(shù)的函數(shù),并且:
在這種情況下,您將擁有一個(gè)通用的“查詢(xún)”功能,區(qū)別僅在于“掃描”功能。
這方面的幾種變化是可能的,但我懷疑你有這個(gè)想法。
使用提供的語(yǔ)句查詢(xún)數(shù)據(jù)庫(kù)。
迭代結(jié)果的行。
對(duì)于每一行,調(diào)用提供的函數(shù),其任務(wù)是掃描該行。
使用
sqlx
基本上是 SQL 驅(qū)動(dòng)的數(shù)據(jù)庫(kù)的包,什么encoding/json
是 JSON 數(shù)據(jù)流:它使用對(duì)您的類(lèi)型的反射來(lái)創(chuàng)建和執(zhí)行 SQL 來(lái)填充它們。通過(guò)這種方式,您將在另一個(gè)層面上獲得可重用性:您根本不會(huì)編寫(xiě)樣板代碼。
使用代碼生成,這是擁有“代碼模板”的Go-native 方式(這就是泛型的意義所在)。
通過(guò)這種方式,您(通常)編寫(xiě)一個(gè) Go 程序,它接受一些輸入(以您希望的任何格式),讀取它并寫(xiě)出一個(gè)或多個(gè)包含 Go 代碼的文件,然后編譯這些文件。
在您的非常簡(jiǎn)單的情況下,您可以從 Go 函數(shù)的模板和某種表開(kāi)始,該表將 SQL 語(yǔ)句映射到要從所選數(shù)據(jù)創(chuàng)建的類(lèi)型。
我會(huì)注意到您的代碼確實(shí)看起來(lái)非常單調(diào)。
沒(méi)有頭腦正常的人會(huì)在 Go 中實(shí)現(xiàn)“存儲(chǔ)庫(kù)模式”,但是只要它能讓你開(kāi)心就好了——我們都在一定程度上被灌輸了我們習(xí)慣的語(yǔ)言/環(huán)境——但是你的connection := r.provider.GetConnection()
樣子令人擔(dān)憂(yōu):Godatabase/sql
與“流行”的環(huán)境和框架截然不同,所以我強(qiáng)烈建議從this和this開(kāi)始。
1(截至 2021 年 5 月 31 日更新)Go 將具有泛型,因?yàn)?a >實(shí)現(xiàn)它們的提案已被接受,并且實(shí)現(xiàn)它們的工作正在進(jìn)行中。

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超10個(gè)贊
如果我誤解了,請(qǐng)?jiān)徫?,但更好的模式可能如下所示?/p>
type RepositoryItem interface {
Name() string // for example
}
type Repository interface {
GetAll() ([]RepositoryItem, error)
}
目前,對(duì)于每種類(lèi)型的存儲(chǔ)庫(kù),您本質(zhì)上都有多個(gè)接口,因此除非您要實(shí)現(xiàn)多種類(lèi)型的RoleRepository,否則您可能沒(méi)有該接口。
從長(zhǎng)遠(yuǎn)來(lái)看,擁有泛型Repository和RepositoryItem接口可能會(huì)使您的代碼更具可擴(kuò)展性(更不用說(shuō)更容易測(cè)試了)。
一個(gè)人為的例子可能是(如果我們假設(shè) aRepository與后端模糊地相關(guān))諸如MySQLRepository和 之類(lèi)的實(shí)現(xiàn)MongoDBRepository。通過(guò)抽象存儲(chǔ)庫(kù)的功能,您可以防止將來(lái)發(fā)生突變。

TA貢獻(xiàn)1848條經(jīng)驗(yàn) 獲得超10個(gè)贊
interface{}是 Go 中的“通用類(lèi)型”。我可以想象做這樣的事情:
package main
import "fmt"
type IRole struct {
RoleId uint
}
type ISaleChannel struct {
Profitable bool
}
type GenericRepo interface{
GetAll([]interface{})
}
// conceptual repo to store all Roles and SaleChannels
type Repo struct {
IRoles []IRole
ISaleChannels []ISaleChannel
}
func (r *Repo) GetAll(ifs []interface{}) {
// database implementation here before type switch
for _, v := range ifs {
switch v := v.(type) {
default:
fmt.Printf("unexpected type %T\n", v)
case IRole:
fmt.Printf("Role %t\n", v)
r.IRoles = append(r.IRoles, v)
case ISaleChannel:
fmt.Printf("SaleChannel %d\n", v)
r.ISaleChannels = append(r.ISaleChannels, v)
}
}
}
func main() {
getter := new(Repo)
// mock slice
data := []interface{}{
IRole{1},
IRole{2},
IRole{3},
ISaleChannel{true},
ISaleChannel{false},
IRole{4},
}
getter.GetAll(data)
fmt.Println("IRoles: ", getter.IRoles)
fmt.Println("ISaleChannels: ", getter.ISales)
}
通過(guò)這種方式,您不必以?xún)蓚€(gè)結(jié)構(gòu)和/或接口結(jié)束IRole和ISale
- 3 回答
- 0 關(guān)注
- 344 瀏覽
添加回答
舉報(bào)