How do I use a TypeConverter in Gorp?

huangapple go评论125阅读模式
英文:

How do I use a TypeConverter in Gorp?

问题

我想使用Gorp从数据库中加载和保存包含特殊类型的结构体。其中之一是用于枚举字符串(如角色):

  1. type Role string
  2. type Account struct {
  3. User string
  4. Role Role
  5. }

这在“开箱即用”情况下无法正常工作。会引发错误消息,例如:

  1. panic: sql: converting Exec argument #0's type: unsupported type user.Role, a string

我怀疑我需要使用gorp.TypeConverter来解决这个问题,但是没有关于如何做到这一点的文档。

你能帮忙吗?

英文:

I would like to use Gorp to load and save structs from the DB that contain specialised types. Amongst other things, this is useful for enumerated strings such as roles:

  1. type Role string
  2. type Account struct {
  3. User string
  4. Role Role
  5. }

This doesn't work "out of the box". An error message is raised such as

  1. panic: sql: converting Exec argument #0's type: unsupported type user.Role, a string

I suspect I need to use a gorp.TypeConverter to solve this, but there is no documentation on how to do this.

Can you help?

答案1

得分: 2

ValuerScanner接口可以实现你想要的功能。以下是一个可工作的示例:

  1. package roleGorp
  2. import (
  3. "gopkg.in/gorp.v1"
  4. "github.com/DATA-DOG/go-sqlmock"
  5. "fmt"
  6. "testing"
  7. "database/sql/driver"
  8. )
  9. type Role string
  10. func (r *Role) Scan(value interface{}) error { *r = Role(value.(string)); return nil }
  11. func (r Role) Value() (driver.Value, error) { return string(r), nil }
  12. type Account struct {
  13. User string `db:"user"`
  14. Role Role `db:"role"`
  15. }
  16. func TestRoleGorp(t *testing.T) {
  17. db, err := sqlmock.New()
  18. if err != nil {
  19. panic(err)
  20. }
  21. dbMap := gorp.DbMap{
  22. Db: db,
  23. Dialect: gorp.MySQLDialect{
  24. Engine: "InnoDB",
  25. },
  26. }
  27. rows := sqlmock.NewRows([]string{"user", "role"}).AddRow("user1", "admin")
  28. sqlmock.ExpectQuery(`SELECT * FROM account LIMIT 1`).WillReturnRows(rows)
  29. dbMap.AddTableWithName(Account{}, "account")
  30. result := &Account{}
  31. err = dbMap.SelectOne(result, "SELECT * FROM account LIMIT 1")
  32. if err != nil {
  33. panic(err)
  34. }
  35. fmt.Printf("%+v\n", *result)
  36. result2 := &Account{
  37. User: "user2",
  38. Role: Role("moderator"),
  39. }
  40. sqlmock.ExpectExec("insert into `account` (`user`,`role`) values (?,?);").WithArgs("user2", "moderator").WillReturnResult(sqlmock.NewResult(1, 1))
  41. err = dbMap.Insert(result2)
  42. if err != nil {
  43. panic(err)
  44. }
  45. }
英文:

Valuer and Scanner interfaces will do what you want. Here is a working example :

  1. package roleGorp
  2. import (
  3. "gopkg.in/gorp.v1"
  4. "github.com/DATA-DOG/go-sqlmock"
  5. "fmt"
  6. "testing"
  7. "database/sql/driver"
  8. )
  9. type Role string
  10. func (r *Role) Scan(value interface{}) error { *r = Role(value.(string)); return nil }
  11. func (r Role) Value() (driver.Value, error) { return string(r), nil }
  12. type Account struct {
  13. User string `db:"user"`
  14. Role Role `db:"role"`
  15. }
  16. func TestRoleGorp(t *testing.T) {
  17. db, err := sqlmock.New()
  18. if err != nil {
  19. panic(err)
  20. }
  21. dbMap := gorp.DbMap{
  22. Db: db,
  23. Dialect: gorp.MySQLDialect{
  24. Engine: "InnoDB",
  25. },
  26. }
  27. rows := sqlmock.NewRows([]string{"user", "role"}).AddRow("user1", "admin")
  28. sqlmock.ExpectQuery(`SELECT \* FROM account LIMIT 1`).WillReturnRows(rows)
  29. dbMap.AddTableWithName(Account{}, "account")
  30. result := &Account{}
  31. err = dbMap.SelectOne(result, "SELECT * FROM account LIMIT 1")
  32. if err != nil {
  33. panic(err)
  34. }
  35. fmt.Printf("%+v\n", *result)
  36. result2 := &Account{
  37. User: "user2",
  38. Role: Role("moderator"),
  39. }
  40. sqlmock.ExpectExec("insert into `account` \\(`user`,`role`\\) values \\(\\?,\\?\\);").WithArgs("user2", "moderator").WillReturnResult(sqlmock.NewResult(1, 1))
  41. err = dbMap.Insert(result2)
  42. if err != nil {
  43. panic(err)
  44. }
  45. }

huangapple
  • 本文由 发表于 2015年6月17日 19:31:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/30890315.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定