当前位置:   article > 正文

mysql bit 对gorm使用何种类型?_mysql bit在go中怎么表示

mysql bit在go中怎么表示

最近项目里面需要查询某一张表,改表某个字段xxx的类型是bit,然后自以为是的使用go的bool来接收该字段值,结果不出意外就出意外了。报错:

 sql/driver: couldn't convert "\x01" into type 

可见,在底层解析过程中,并不能把mysql的bit类型转化成go的bool。

 我们跟踪源码进去底层可以看到,在database/sql/driver/type.go 文件中对目标为bool类型的处理如下

  1. var Bool boolType
  2. type boolType struct{}
  3. var _ ValueConverter = boolType{}
  4. func (boolType) String() string { return "Bool" }
  5. func (boolType) ConvertValue(src any) (Value, error) {
  6. switch s := src.(type) {
  7. case bool:
  8. return s, nil
  9. case string:
  10. b, err := strconv.ParseBool(s)
  11. if err != nil {
  12. return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
  13. }
  14. return b, nil
  15. case []byte:
  16. b, err := strconv.ParseBool(string(s))
  17. if err != nil {
  18. return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
  19. }
  20. return b, nil
  21. }
  22. // XXXXXXXX 略
  23. }

目前我们在查询mysql后拿到的src 其实是[]uint8类型(实际上就是 []byte),接着就进入了case []byte 分支,然后这里直接把原数据通过string(s) 强制转换成字符串,导致原来的值 0x01 变成了字符面值为  SOH (通过查看ASCII表)代表标题开始的字符。所以调用strconv.ParseBool 必定失败,因为s根本不符合bool字符量。从而导致错误发生。那么我们要怎么处理这种类型呢?

其实sql包提供了,scan接口:如下

  1. type Scanner interface {
  2. // Scan assigns a value from a database driver.
  3. //
  4. // The src value will be of one of the following types:
  5. //
  6. // int64
  7. // float64
  8. // bool
  9. // []byte
  10. // string
  11. // time.Time
  12. // nil - for NULL values
  13. //
  14. // An error should be returned if the value cannot be stored
  15. // without loss of information.
  16. //
  17. // Reference types such as []byte are only valid until the next call to Scan
  18. // and should not be retained. Their underlying memory is owned by the driver.
  19. // If retention is necessary, copy their values before the next call to Scan.
  20. Scan(src any) error
  21. }

只要你的类型实现了该接口,那么就可以操作bit类型了,于是我自定义了类型来接收bit类型。

  1. type MyBool bool
  2. func (b *MyBool) Value() (driver.Value, error) {
  3. result := make([]uint8, 1)
  4. if *b {
  5. result[0] = uint8(1)
  6. } else {
  7. result[0] = 0
  8. }
  9. return result, nil
  10. }
  11. func (b *MyBool) Scan(v interface{}) error {
  12. bytes := v.([]uint8)
  13. if bytes[0] == 0 {
  14. *b = false
  15. } else {
  16. *b = true
  17. }
  18. return nil
  19. }

在对应字段上使用该类型,你就可以接受mysql 的bit类型了。(注意这里类型的方法一定是指针对应的方法,否者赋值失败)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/836293
推荐阅读
相关标签
  

闽ICP备14008679号