使用时go-sql-driver,感觉就像我在重新发明轮子。我习惯于使用具有User与数据库模型严格相关的数据模型(如类)的语言。然后,您当然可以具有要在API上公开的内容的其他模型,但是仍然有数据库对象的模型。在Go中,我不确定如何做到这一点的最佳方法。下面是一个GetUserByEmail功能。
go-sql-driver
User
GetUserByEmail
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 }
这里的一个问题是,如果我更改数据库中password和的顺序email,我的应用程序将以静默方式切换它们,并且不会出现任何错误。这是一种可怕的危险行为。可以Scan()以某种方式取得钥匙还是可以其他方式进行?我当然可以查看Columns()并从那里将索引顺序作为一个int(尽管Go似乎没有内置该函数)并将其映射到我的User变量,但是我真的需要对我的所有数据库进行所有这些操作吗?方法?它是抽象的吗?还是我需要自己做?
password
email
Scan()
Columns()
这里的一个问题是,如果我更改数据库中密码和电子邮件的顺序,我的应用程序将以静默方式进行切换,并且不会出错。
可以说,解决此问题的最佳方法就是根本不使用SELECT *-始终为您的列命名。问题*实际上可能比您描述的要大- 如果添加新列,您的查询甚至不需要什么?您的代码将无故中断。
SELECT *
*
但是关于您的更大问题…
可以Scan()以某种方式取得钥匙还是可以其他方式进行?
标准库sql程序包不提供此功能。但是,可以使用第三方库。sqlx可能是最受欢迎的一种,它与标准库最相似。这是我的建议。
sql
如果您更喜欢痛苦,痛苦和永无止境的流血冲突,那么诸如gorm或gorp之类的事情也是可能的。