mysql bit 对gorm使用何种类型?

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

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

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

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

var Bool boolType

type boolType struct{}

var _ ValueConverter = boolType{}

func (boolType) String() string { return "Bool" }

func (boolType) ConvertValue(src any) (Value, error) {
	switch s := src.(type) {
	case bool:
		return s, nil
	case string:
		b, err := strconv.ParseBool(s)
		if err != nil {
			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
		}
		return b, nil
	case []byte:
		b, err := strconv.ParseBool(string(s))
		if err != nil {
			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
		}
		return b, nil
	}

 // XXXXXXXX 略
}

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

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

type Scanner interface {
	// Scan assigns a value from a database driver.
	//
	// The src value will be of one of the following types:
	//
	//    int64
	//    float64
	//    bool
	//    []byte
	//    string
	//    time.Time
	//    nil - for NULL values
	//
	// An error should be returned if the value cannot be stored
	// without loss of information.
	//
	// Reference types such as []byte are only valid until the next call to Scan
	// and should not be retained. Their underlying memory is owned by the driver.
	// If retention is necessary, copy their values before the next call to Scan.
	Scan(src any) error
}

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


type MyBool bool

func (b *MyBool) Value() (driver.Value, error) {
	result := make([]uint8, 1)
	if *b {
		result[0] = uint8(1)
	} else {
		result[0] = 0
	}
	return result, nil
}
func (b *MyBool) Scan(v interface{}) error {
	bytes := v.([]uint8)

	if bytes[0] == 0 {
		*b = false
	} else {
		*b = true
	}
	return nil
}

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

  • 11
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值