Golang repostiory模式

sol*_*w74 5 go repository-pattern

我尝试在Go app(简单的Web服务)中实现存储库模式,并尝试找到更好的方法来转义代码重复.

这是一个代码

接口是:

type IRoleRepository interface {
    GetAll() ([]Role, error)
}

type ISaleChannelRepository interface {
    GetAll() ([]SaleChannel, error)
}
Run Code Online (Sandbox Code Playgroud)

并实施:

func (r *RoleRepository) GetAll() ([]Role, error) {
        var result []Role
        var err error
        var rows *sql.Rows

        if err != nil {
            return result, err
        }

        connection := r.provider.GetConnection()
        defer connection.Close()

        rows, err = connection.Query("SELECT Id,Name FROM Position")
        defer rows.Close()

        if err != nil {
            return result, err
        }

        for rows.Next() {
            entity := new(Role)
            err = sqlstruct.Scan(entity, rows)

            if err != nil {
                return result, err
            }

            result = append(result, *entity)
        }
        err = rows.Err()
        if err != nil {
            return result, err
        }

        return result, err
    }

    func (r *SaleChannelRepository) GetAll() ([]SaleChannel, error) {
        var result []SaleChannel
        var err error
        var rows *sql.Rows

        if err != nil {
            return result, err
        }

        connection := r.provider.GetConnection()
        defer connection.Close()

        rows, err = connection.Query("SELECT DISTINCT SaleChannel 'Name' FROM Employee")
        defer rows.Close()

        if err != nil {
            return result, err
        }

        for rows.Next() {
            entity := new(SaleChannel)
            err = sqlstruct.Scan(entity, rows)

            if err != nil {
                return result, err
            }

            result = append(result, *entity)
        }
        err = rows.Err()
        if err != nil {
            return result, err
        }

        return result, err
    }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,差异只有几个字.我尝试从C#中找到类似Generics的东西,但没有找到.

谁能帮我?

kos*_*tix 22

不,Go没有仿制药,也不会在可预见的未来拥有它们.

你有三个选择:

  • 重构您的代码,以便您拥有一个接受SQL语句和另一个函数的函数,并且:

    1. 使用提供的语句查询DB.
    2. 迭代结果的行.
    3. 对于每一行,调用提供的函数,其任务是扫描行.

    在这种情况下,您将拥有一个通用的"查询"功能,而差异仅在于"扫描"功能.

    有几种变化是可能的,但我怀疑你有这个想法.

  • 使用sqlx基本上是SQL驱动的数据库的包encoding/json对JSON数据流是什么:它使用类型的反射来创建和执行SQL来填充它们.

    这样你就可以在另一个层面上获得可重用性:你根本就不会编写样板代码.

  • 使用代码生成,这是具有"代码模板" Go-native方式(这是泛型的内容).

    这样,你(通常)编写一个Go程序,它接受一些输入(以你想要的任何格式),读取它并写出一个或多个包含Go代码的文件,然后编译.

    在您非常简单的情况下,您可以从Go函数的模板和某种表格开始,该表格将SQL语句映射到要从所选数据创建的类型.


我注意到你的代码确实看起来非常单调.

在他们正确的思想中没有人在Go中实现"存储库模式",但这有点好,只要它让你开心 - 我们都在某种程度上被我们习以为常的语言/环境灌输,但你的connection := r.provider.GetConnection()看起来令人担忧:围棋的database/sql是"流行"的环境和框架完全不同,所以我会强烈建议先从这个这个.

  • @Roylee,恐怕您会迷上那些讨厌的“模式”,就像许多人一样。当遇到问题时,软件开发并不是要查看一系列模式以找出适合的模式。我建议1)停止思考模式;2)看一下这门语言有什么特点;3)看你的问题;4)找出哪些语言功能可以提供帮助。 (3认同)
  • `...这不是在遇到问题时,通过查看模式目录来查看哪种模式适合。`,这直刺我的心。我现在明白了,这是非常好的建议。谢谢@kostix (2认同)