【问题标题】:Calling the same function on two different structs在两个不同的结构上调用相同的函数
【发布时间】:2019-03-26 13:35:44
【问题描述】:

我有两个函数接受指向不同结构的不同指针,但这些结构具有相同的底层函数。

func Save(db *sql.DB) error {
  db.Prepare(query)
}

func TxSave(tx *sql.Tx) error {
  tx.Prepare(query)
}

我不想在将来需要扩展此功能时对这两个功能进行更改。在这种情况下,我如何在 golang 中遵守 DRYness?

【问题讨论】:

    标签: go


    【解决方案1】:

    创建一个接口如:

    type SQLRunner interface{
        Prepare(query string) (*sql.Stmt, error)
        PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
        Query(query string, args ...interface{}) (*Rows, error)
        QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
        // add as many method shared by both sql.Tx qnd sql.DB
        // ...
    } 
    

    然后创建一个采用该接口的方法:

    func Save(s SQLRunner) error {
        s.Prepare()
    }
    

    在 go 接口实现是隐式的,所以你只需要将 *sql.Tx 或 *sql.DB 传递给保存函数:

    Save(tx)
    Save(db)
    

    这里有一篇关于 go 接口的好博文:http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go

    【讨论】:

    • 我实际上在你面前想出了同样的答案!我会接受这个作为正确答案,因为它有更多的细节。
    • 好你发现了。 Go 中的隐式接口实现是一个非常有用的功能!
    【解决方案2】:

    哇,我想我爱上了围棋。我实际上可以通过创建自己的界面来做到这一点。

    type Saver interface {
      Prepare(query string) (*sql.Stmt, error)
    }
    
    func Save(db *sql.DB) error {
      return GenericSave(db)
    }
    
    func TxSave(tx *sql.Tx) error {
      return GenericSave(tx)
    }
    
    func GenericSave(saver Saver) error {
      stmt := saver.Prepare(query)
      // Do rest with saver
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 2016-12-08
      • 2019-10-14
      • 2022-10-30
      相关资源
      最近更新 更多