之前我使用过Java,因此数据库表中的某些列类型为bit(1)
。但现在我想使用beego重建我的项目,我不想改变我的数据库表(需要做很多)。我在我的项目中使用了beego的orm。那么我应该使用哪种Go类型?
这样的表和删除的列有问题:
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | varchar(255) | NO | PRI | NULL | |
| created_time | datetime | YES | | NULL | |
| deleted | bit(1) | NO | | NULL | |
| updated_time | datetime | YES | | NULL | |
| icon_class | varchar(255) | YES | | NULL | |
| mark | varchar(255) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| parent | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
像这样结构:
type BaseModel struct {
Id string `orm:"pk";form:"id"`
CreatedTime time.Time `orm:"auto_now_add;type(datetime)";form:"-"`
UpdatedTime time.Time `orm:"auto_now;type(datetime)";form:"-"`
Deleted bool `form:"-"`
}
当我在代码中使用bool时,错误如下:
`[0]` convert to `*orm.BooleanField` failed, field: shareall-go/models.Category.BaseModel.Deleted err: strconv.ParseBool: parsing "\x00": invalid syntax
答案 0 :(得分:1)
Sqlx还为这种情况创建了一个自定义的bool数据类型,并且工作正常。 Link to related code
// BitBool is an implementation of a bool for the MySQL type BIT(1).
// This type allows you to avoid wasting an entire byte for MySQL's boolean type TINYINT.
type BitBool bool
// Value implements the driver.Valuer interface,
// and turns the BitBool into a bitfield (BIT(1)) for MySQL storage.
func (b BitBool) Value() (driver.Value, error) {
if b {
return []byte{1}, nil
} else {
return []byte{0}, nil
}
}
// Scan implements the sql.Scanner interface,
// and turns the bitfield incoming from MySQL into a BitBool
func (b *BitBool) Scan(src interface{}) error {
v, ok := src.([]byte)
if !ok {
return errors.New("bad []byte type assertion")
}
*b = v[0] == 1
return nil
}
答案 1 :(得分:0)
我应该使用哪种Go类型?
通常,这取决于您使用数据的方式多于存储方式。正如您所想,您尝试将其用作Bool
(这是有道理的)但是出错了。
问题是MySQL存储BIT
的方式与存储BOOL
的方式不同,Go MySQL驱动程序需要MySQL BOOL
。您可以使用实现sql.Scanner接口的自定义类型来解决此问题。因为你可能只有两个(或者三个,如果算上NULL
)输入,它应该相当容易。请注意,此代码不完整且未经测试。它旨在作为指南,而不是复制和粘贴解决方案。
type MyBool bool
func (b *MyBool) Scan(src interface{}) error {
str, ok := src.(string)
if !ok {
return fmt.Errorf("Unexpected type for MyBool: %T", src)
}
switch str {
case "\x00":
v := false
*b = v
case "\x01":
v := true
*b = v
}
return nil
}