自定义的字符串到布尔值的转换,适用于sql/driver和Gorm。

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

Custom string to bool conversion for sql/driver and Gorm

问题

我正在尝试创建一个字符串到布尔值的转换数据类型,为了进一步解释我想要实现的目标,我将给出一个字符串连接的示例

当使用gorm时,以下结构体在字段2和字段3处会失败,如果你调试它,它基本上会抛出一个错误,错误信息为sql: Scan error on column index 2, name "nlfieldTwo": unsupported Scan, storing driver.Value type []uint8 into type *[]string;

type Name struct {
   FieldOne   *String   `json:"fieldOne,omitempty"   gorm:"column:nlfieldOne"`
   FieldTwo   *[]String `json:"fieldTwo,omitempty"   gorm:"column:nlfieldTwo"`
   FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
}

解决方法是创建自己的类型:

type StringConcat []string

func (s *StringConcat) Scan(value interface{}) error {
	str, _ := value.([]byte)
	*s = strings.Split(string(str), ",")
	return nil
}

func (s StringConcat) Value() (driver.Value, error) {
	if len(s) == 0 {
		return nil, nil
	}
	return strings.Join(s, ","), nil
}

然后将FieldTwo *[]String替换为FieldTwo StringConcat

问题

我想为布尔类型做类似的处理,就像FieldFour中所示:

type Name struct {
   FieldOne   *String   `json:"fieldOne,omitempty"   gorm:"column:nlfieldOne"`
   FieldTwo   *[]String `json:"fieldTwo,omitempty"   gorm:"column:nlfieldTwo"`
   FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
   FieldFour  *bool     `json:"fieldThree,omitempty" gorm:"column:nlfieldFour"`
}

FieldFour是一个字符串类型,所以如果我尝试上述方法,它将会失败并抛出错误sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "None" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "Creative" into type bool; ....... and so on

我想将其转换为布尔值,但是,我不想检查空字符串和"None"字符串值,如上面的错误所示,只要它们是其他字符串值,我希望返回true,如果没有值,则返回false。

我尝试查看strconv.FormatBool,但是我无法找到一种方法来实现这个。

英文:

I am trying to create a string to bool converstion data type, to further explain what I am trying to achieve I will give an example of a string concat.

The following struct will fail at field 2 and 3 when using gorm, if you debug this it will basically throw an error saying sql: Scan error on column index 2, name "nlfieldTwo": unsupported Scan, storing driver.Value type []uint8 into type *[]string;

type Name struct {
   FieldOne   *String   `json:"fieldOne,omitempty"   gorm:"column:nlfieldOne"`
   FieldTwo   *[]String `json:"fieldTwo,omitempty"   gorm:"column:nlfieldTwo"`
   FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
}

A fix around this is to create your own type

type StringConcat []string

func (s *StringConcat) Scan(value interface{}) error {
	str, _ := value.([]byte)
	// log.Println(value)
	// if !ok {
	// 	return errors.New(fmt.Sprint("Failed to unmarshal value:", value))
	// }

	*s = strings.Split(string(str), ",")
	return nil
}

// Value return json value, implement driver.Valuer interface
func (s StringConcat) Value() (driver.Value, error) {
	if len(s) == 0 {
		return nil, nil
	}
	return strings.Join(s, ","), nil
}

and then simply replace FieldTwo *[]String with FieldTwo StringConcat

THE PROBLEM

I am trying to do something similar for a bool type as seen in FieldFour

type Name struct {
   FieldOne   *String   `json:"fieldOne,omitempty"   gorm:"column:nlfieldOne"`
   FieldTwo   *[]String `json:"fieldTwo,omitempty"   gorm:"column:nlfieldTwo"`
   FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
   FieldFour  *bool     `json:"fieldThree,omitempty" gorm:"column:nlfieldFour"`
}

FieldFour is a string type so if I try doing the above it will simply fail and throw an error sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "None" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "Creative" into type bool; ....... and so on

I am trying to convert that to return a bool however, I do not want to check for empty and None string values as shown in the error above "" and "None" everything else I want to return a true if they got a string value or false if they got nothing.

I tried looking into strconv.FormatBool but I could not figure out a way of doing this.

答案1

得分: 1

这应该可以通过实现自定义类型来实现:

type MyBool bool

func (s *MyBool) Scan(value interface{}) error {
	b, _ := value.(string)
	if b == "" || b == "None" {
		*s = false
	} else {
		*s = true
	}
	return nil
}

func (s MyBool) Value() (driver.Value, error) {
	if s {
		return "true", nil
	}
	return "", nil
}

我不确定我是否正确理解了所需的映射,但你应该能够进行调整。在Scan中定义你的stringbool的映射,反之亦然在Value中定义。

英文:

That should be doable by implementing your custom type as well:

type MyBool bool

func (s *MyBool) Scan(value interface{}) error {
	b, _ := value.(string)
	if b == "" || b == "None" {
		*s = false
	} else {
		*s = true
	}
	return nil
}

func (s MyBool) Value() (driver.Value, error) {
	if s {
		return "true", nil
	}
	return "", nil
}

I'm not sure, if I understood the required mapping right, but you should be able to adapt it. Define your mapping of string to bool in Scan and vice versa in Value.

huangapple
  • 本文由 发表于 2022年6月7日 14:59:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/72527074.html
匿名

发表评论

匿名网友

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

确定