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

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

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;

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

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

  1. type StringConcat []string
  2. func (s *StringConcat) Scan(value interface{}) error {
  3. str, _ := value.([]byte)
  4. *s = strings.Split(string(str), ",")
  5. return nil
  6. }
  7. func (s StringConcat) Value() (driver.Value, error) {
  8. if len(s) == 0 {
  9. return nil, nil
  10. }
  11. return strings.Join(s, ","), nil
  12. }

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

问题

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

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

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;

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

A fix around this is to create your own type

  1. type StringConcat []string
  2. func (s *StringConcat) Scan(value interface{}) error {
  3. str, _ := value.([]byte)
  4. // log.Println(value)
  5. // if !ok {
  6. // return errors.New(fmt.Sprint("Failed to unmarshal value:", value))
  7. // }
  8. *s = strings.Split(string(str), ",")
  9. return nil
  10. }
  11. // Value return json value, implement driver.Valuer interface
  12. func (s StringConcat) Value() (driver.Value, error) {
  13. if len(s) == 0 {
  14. return nil, nil
  15. }
  16. return strings.Join(s, ","), nil
  17. }

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

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

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

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

  1. type MyBool bool
  2. func (s *MyBool) Scan(value interface{}) error {
  3. b, _ := value.(string)
  4. if b == "" || b == "None" {
  5. *s = false
  6. } else {
  7. *s = true
  8. }
  9. return nil
  10. }
  11. func (s MyBool) Value() (driver.Value, error) {
  12. if s {
  13. return "true", nil
  14. }
  15. return "", nil
  16. }

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

英文:

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

  1. type MyBool bool
  2. func (s *MyBool) Scan(value interface{}) error {
  3. b, _ := value.(string)
  4. if b == "" || b == "None" {
  5. *s = false
  6. } else {
  7. *s = true
  8. }
  9. return nil
  10. }
  11. func (s MyBool) Value() (driver.Value, error) {
  12. if s {
  13. return "true", nil
  14. }
  15. return "", nil
  16. }

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:

确定