3 回答
TA贡献1853条经验 获得超6个赞
不,Go 没有泛型并且在可预见的未来不会有它们¹。
您有三个选择:
重构您的代码,以便您拥有一个接受 SQL 语句和另一个函数的函数,并且:
在这种情况下,您将拥有一个通用的“查询”功能,区别仅在于“扫描”功能。
这方面的几种变化是可能的,但我怀疑你有这个想法。
使用提供的语句查询数据库。
迭代结果的行。
对于每一行,调用提供的函数,其任务是扫描该行。
使用
sqlx
基本上是 SQL 驱动的数据库的包,什么encoding/json
是 JSON 数据流:它使用对您的类型的反射来创建和执行 SQL 来填充它们。通过这种方式,您将在另一个层面上获得可重用性:您根本不会编写样板代码。
使用代码生成,这是拥有“代码模板”的Go-native 方式(这就是泛型的意义所在)。
通过这种方式,您(通常)编写一个 Go 程序,它接受一些输入(以您希望的任何格式),读取它并写出一个或多个包含 Go 代码的文件,然后编译这些文件。
在您的非常简单的情况下,您可以从 Go 函数的模板和某种表开始,该表将 SQL 语句映射到要从所选数据创建的类型。
我会注意到您的代码确实看起来非常单调。
没有头脑正常的人会在 Go 中实现“存储库模式”,但是只要它能让你开心就好了——我们都在一定程度上被灌输了我们习惯的语言/环境——但是你的connection := r.provider.GetConnection()
样子令人担忧:Godatabase/sql
与“流行”的环境和框架截然不同,所以我强烈建议从this和this开始。
¹(截至 2021 年 5 月 31 日更新)Go 将具有泛型,因为实现它们的提案已被接受,并且实现它们的工作正在进行中。
TA贡献1802条经验 获得超10个赞
如果我误解了,请原谅我,但更好的模式可能如下所示:
type RepositoryItem interface {
Name() string // for example
}
type Repository interface {
GetAll() ([]RepositoryItem, error)
}
目前,对于每种类型的存储库,您本质上都有多个接口,因此除非您要实现多种类型的RoleRepository,否则您可能没有该接口。
从长远来看,拥有泛型Repository和RepositoryItem接口可能会使您的代码更具可扩展性(更不用说更容易测试了)。
一个人为的例子可能是(如果我们假设 aRepository与后端模糊地相关)诸如MySQLRepository和 之类的实现MongoDBRepository。通过抽象存储库的功能,您可以防止将来发生突变。
TA贡献1848条经验 获得超10个赞
interface{}是 Go 中的“通用类型”。我可以想象做这样的事情:
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)
}
通过这种方式,您不必以两个结构和/或接口结束IRole和ISale
- 3 回答
- 0 关注
- 280 浏览
添加回答
举报