【问题标题】:How to use rows.Scan of Go's database/sql如何使用 rows.Scan Go 的数据库/sql
【发布时间】:2019-10-24 19:11:50
【问题描述】:

我使用 database/sql 并定义了到 DB 表列(标签字段)的结构映射:

// Users ...
type Users struct {
    ID            int64  `field:"id"`                      
    Username      string `field:"username"`           
    Password      string `field:"password"`           
    Tel           string `field:"tel"`                   
}

然后我查询:

        rows, err := db.Query(sql)  // select * from users
        if err != nil {
            fmt.Println(err)
        }
        defer rows.Close()
        for rows.Next() {
            user := new(Users)

            // works but I don't think it is good code for too many columns
            err = rows.Scan(&user.ID, &user.Username, &user.Password, &user.Tel)

            // TODO: How to scan in a simple way 


            if err != nil {
                fmt.Println(err)
            }
            fmt.Println("user: ", user)
            list = append(list, *user)
        }
        if err := rows.Err(); err != nil {
            fmt.Println(err)
        }

正如您在rows.Scan() 中看到的那样,我必须编写所有列,而且我认为这不是 20 列或更多列的好方法。

如何清晰地扫描。

【问题讨论】:

  • 让你的类型实现扫描器。或者使用 github.com/jmoiron/sqlx。
  • 我只用过database/sqlgithub.com/go-sql-driver/mysql
  • @Rife 您可以使用reflect 自己完成此任务,但老实说,如果您真的想要这个,您可能应该考虑采用sqlx,因为它已经为您解决了这个问题。
  • @DominicBarnes 进一步反映了由于性能问题而被认为是不良做法。
  • @alexfwulf 它有影响,但我指出sqlx 因为它实现了这个解决方案并使用reflect 这样做,所以你不需要自己实现它。

标签: go


【解决方案1】:

您可以考虑使用 jmoiron 的 sqlx 包。它支持分配给结构。

自述文件摘录:

type Place struct {
    Country string
    City    sql.NullString
    TelCode int
}
 places := []Place{}
 err = db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
 if err != nil {
     fmt.Println(err)
      return
 }

【讨论】:

  • sqlx 是一个很好的包,但是如何仅通过 database/sql 和 github.com/go-sql-driver/mysql 来实现。
【解决方案2】:

这是使用反射的好习惯:

    for rows.Next() {
        user := Users{}

        s := reflect.ValueOf(&user).Elem()
        numCols := s.NumField()
        columns := make([]interface{}, numCols)
        for i := 0; i < numCols; i++ {
            field := s.Field(i)
            columns[i] = field.Addr().Interface()
        }

        err := rows.Scan(columns...)
        if err != nil {
            log.Fatal(err)
        }
        log.Println(user)
    }

【讨论】:

  • 如果我的Users 接口也有json tag 怎么办?我尝试了这种方法,但它不起作用。
猜你喜欢
  • 2023-03-10
  • 2015-07-25
  • 1970-01-01
  • 2017-12-15
  • 2020-08-20
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
相关资源
最近更新 更多