douxing6434 2018-01-17 16:10
浏览 82
已采纳

go-sql-driver Scan()的命名键

When using the go-sql-driver it feels like I'm re-inventing the wheel a little bit. I'm used to languages where you have a data model (like a User class) which is strictly related to the database model. Then you can have additional models for what you want to expose on an API of course, but still, you have a model for the database object. In Go I'm not sure how to do this the best way. Below is a GetUserByEmail function.

func GetUserByEmail(email string) (*myapp.User, error) {
    smt, err := database.Prepare("SELECT * FROM users WHERE email = ?")

    if err != nil {
        return nil, err
    }

    rows, err := smt.Query(email)
    defer rows.Close()

    if err != nil {
        return nil, err
    }

    var users []*myapp.User

    for rows.Next() {
        var id string
        var confirmed bool
        var password string
        var email string
        var updated string
        var created string
        err = rows.Scan(&id, &confirmed, &password, &email, &updated, &created)

        if err != nil {
            return nil, err
        }

        user := myapp.User{id, confirmed, created, password, email, updated}
        users = append(users, &user)
    }

    if users == nil || len(users) == 0 {
        return nil, errors.New("User not found.")
    }

    if len(users) != 1 {
        return nil, errors.New("Nr of users fetched: " + string(len(users)) + ". Expected: 1.")
    }

    return users[0], nil
}

One problem here is that if I change the order of password and email in the database, my application will silently switch those and I will get no error. That's an awful and dangerous behavior. Can Scan() take keys somehow or can I do this in some other way? I could of course look at Columns() and take the index order from there as an int (although Go doesn't seem to have that function built in) and map it to my User variables, but do I really need to do all that for all my database methods? Is it abstracted somewhere or do I need to do that myself?

  • 写回答

1条回答 默认 最新

  • douzao2992 2018-01-17 17:06
    关注

    One problem here is that if I change the order of password and email in the database, my application will silently switch those and I will get no error.

    Arguably the best solution to this problem is simply not to use SELECT * -- always name your columns. The problems with * can actually be larger than what you describe--what if new columns are added, which your query doesn't even need? Your code will break, for no useful reason.

    But on to your larger question...

    Can Scan() take keys somehow or can I do this in some other way?

    The standard library sql package does not provide this functionality. However, there are third-party libraries that do. sqlx is probably the most popular one, which is most similar to the standard library. It is my recommendation.

    If you prefer pain, suffering, and never-ending bloodshed, something like gorm or gorp are also possibilities.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值