Your Question
I wrote the following code referring to this document:
func connection() *gorm.DB {
dsn := "root:root@tcp(localhost:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
return db.Debug()
}
type User struct {
ID int64 `json:"ID,omitempty" gorm:"primaryKey"`
RoleIDs RoleIds `json:"roleIds,omitempty" gorm:"type:varchar(250);"`
}
func (User) TableName() string {
return "user"
}
type RoleIds []int64
func (m *RoleIds) Scan(val interface{}) error {
s := val.([]byte)
ss := strings.Split(string(s), ",")
for _, v := range ss {
parseInt, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return err
}
*m = append(*m, parseInt)
}
return nil
}
func (m *RoleIds) Value() (driver.Value, error) {
if m == nil || len(*m) == 0 {
return "", nil
}
strs := make([]string, len(*m))
for i, v := range *m {
strs[i] = strconv.FormatInt(v, 10)
}
return strings.Join(strs, ","), nil
}
func main() {
conn := connection()
u := User{
ID: 0,
RoleIDs: []int64{1, 2, 3, 4},
}
err := conn.Create(&u).Error
if err != nil {
println(err.Error())
}
}
error info is :
2024/04/15 17:48:58 E:/xxxx/demo4gorm/main.go:65 Error 1241 (21000): Operand should contain 1 column(s)
[124.763ms] [rows:0] INSERT INTO `user` (`role_ids`) VALUES ((1,2,3,4))
Error 1241 (21000): Operand should contain 1 column(s)
The document you expected this should be explained
https://gorm.io/zh_CN/docs/models.html
Expected answer
Is my code implemented correctly? Are there any other implementation methods?
Comment From: ivila
@llh4github your code has bug, setting those build constraints and you will see your driver.Valuer has not been implement yet.
// import "database/sql/driver"
var _ driver.Valuer = (RoleIds)(nil) // you will get compile error at this line
// import "database/sql"
var _ sql.Scanner = (*RoleIds)(nil)
what you should do is change your Value method
func (m RoleIds) Value() (driver.Value, error) {
if len(m) == 0 {
return "", nil
}
strs := make([]string, len(m))
for i, v := range m {
strs[i] = strconv.FormatInt(v, 10)
}
return strings.Join(strs, ","), nil
}
and for suggestion, in your Scanner method, do not assert the value must be []byte, it could be other type in other drivers, for example, a string.