Home > Backend Development > Golang > Gorm returns scanner error on custom string type

Gorm returns scanner error on custom string type

王林
Release: 2024-02-11 18:21:21
forward
1156 people have browsed it

Gorm 在自定义字符串类型上返回扫描仪错误

php editor banana introduction: In Gorm, when you try to perform a scan operation on a custom string type, you may encounter errors. This issue may cause the scanner to fail to parse the string correctly, resulting in program errors. This is because Gorm uses the `Scan` method by default to scan string type fields, but for custom string types, the `Scan` method may not handle it correctly. The solution to this problem is to use the `Value` method to manually parse the string to ensure that the program executes correctly. This way you can avoid running into problems with scanner errors when using Gorm.

Question content

I wrote the following entities:

type datacategory string

const (
    datacategory1 datacategory = "category1"
    datacategory2 datacategory = "category2"
)

type data struct {
    name            string         `json:"name"`
    categories      []datacategory `json:"category" gorm:"type:text[]"`
}
Copy after login

I manually created a row in the database and filled the categories array type with category1 and category2.

But the following error occurs when reading data:

sql: scan error on column index 19, name "category": unsupported scan, storing driver.value type string into type *[]datacategory
Copy after login

Example value method:

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

    v := []string{}
    for _, dc := range s {
        v = append(v, string(dc))
    }
    result := fmt.Sprintf("{%s}", strings.Join(v, ","))
    return result, nil
}
Copy after login

Workaround

The following example assumes you are using postgresql as the rdbms and the datacategory value does not contain commas or unescaped single quotes.

// declare the custom type
type datacategoryslice []datacategory
Copy after login
// implement driver.valuer to encode the value into the
// correct format that is accepted by the target rdbms
func (s datacategoryslice) value() (driver.value, error) {
    if s == nil {
        return nil, nil
    }
    if len(s) == 0 {
        return []byte(`{}`), nil
    }

    v := []byte(`{`)
    for i := range s {
        v = append(v, s[i]...)
        v = append(v, ',')
    }
    v[len(v)-1] = '}' // replace last comma with closing brace
    return v, nil
}
Copy after login
// implement scanner to decode the raw source
// value as retrieved from the database
func (s *datacategoryslice) scan(src any) error {
    var data []byte
    switch v := src.(type) {
    case []byte:
        data = v
    case string:
        data = []byte(v)
    case nil:
        return nil
    default:
        return fmt.errorf("unsupported type: %t", src)
    }
    if len(data) == 0 {
        return nil
    }
    data = data[1:len(data)-1] // remove surrounding braces
    for _, v := range bytes.split(data, []byte{','}) {
        *s = append(*s, datacategory(v))
    }
    return nil
}
Copy after login

Alternatively, if returning []byte<code> from value() (driver.value, error) does not work, e.g. it results in "Error: malformed array literal: <hex field value representation> (sqlstate 22p02)", then you can try using string as the return type.

Example from @kozhioyrin

// implement driver.Valuer to encode the value into the
// correct format that is accepted by the target RDBMS
func (s DataCategorySlice) Value() (driver.Value, error) {
    if s == nil {
        return nil, nil
    }
    if len(s) == 0 {
        return "{}", nil
    }

    v := []string{}
    for _, dc := range s {
        v = append(v, string(dc))
    }
    result := fmt.Sprintf("{%s}", strings.Join(v, ","))
    return result, nil
}
Copy after login

The above is the detailed content of Gorm returns scanner error on custom string type. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template