Gorm+MySQL使用UUID作为Model ID无法创建数据的求助
解决方案:Gorm + PlanetScale 使用 UUID 作为主键
核心问题分析
你遇到的所有错误根源在于继承了gorm.Model但同时自定义了ID uuid.UUID字段。gorm.Model内置的ID字段类型是uint,会导致Gorm将数据库表的id字段创建为整数类型,而你传入的UUID是字符串/UUID类型,必然出现类型不匹配、数据截断等错误。
步骤1:移除gorm.Model继承,自定义基础模型
创建包含时间字段的自定义基础模型,避免与内置ID冲突:
package models import ( "time" "github.com/google/uuid" "gorm.io/gorm" ) // 自定义基础模型,替代gorm.Model type BaseModel struct { CreatedAt time.Time `gorm:"column:created_at"` UpdatedAt time.Time `gorm:"column:updated_at"` DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index"` } type User struct { BaseModel ID uuid.UUID `gorm:"primaryKey;type:char(36);default:uuid()"` Name string Email string LeagueID string League League `gorm:"foreignKey:LeagueID"` }
标签说明:
type:char(36):适配标准UUID的字符串长度(含连字符共36位),PlanetScale的MySQL支持该类型default:uuid():让数据库自动生成UUID(PlanetScale兼容MySQL的uuid()函数)primaryKey:标记该字段为主键
步骤2:调整创建用户的逻辑
方式1:让数据库自动生成UUID
无需手动设置ID,Gorm会触发数据库的默认值生成逻辑:
func CreateUser(c *gin.Context) { newUser := models.User{Name: "John Doe", LeagueID: "id"} result := initializers.DB.Create(&newUser) if result.Error != nil { panic("Failed to create user: " + result.Error.Error()) } c.JSON(http.StatusCreated, newUser) }
方式2:手动生成UUID
如果需要在代码中提前生成UUID,直接赋值即可:
func CreateUser(c *gin.Context) { newUser := models.User{ ID: uuid.New(), Name: "John Doe", LeagueID: "id", } result := initializers.DB.Create(&newUser) if result.Error != nil { panic("Failed to create user: " + result.Error.Error()) } c.JSON(http.StatusCreated, newUser) }
步骤3:确保数据库表结构正确
如果使用Gorm的AutoMigrate,上述模型配置会自动创建char(36)类型的id字段。如果手动建表,执行以下SQL:
CREATE TABLE users ( id CHAR(36) NOT NULL PRIMARY KEY DEFAULT uuid(), name VARCHAR(255) NOT NULL, email VARCHAR(255), league_id VARCHAR(255), created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, deleted_at DATETIME );
额外注意事项
- 禁止同时使用
gorm.Model和自定义ID字段,避免字段映射冲突 - 确保使用的UUID包为
github.com/google/uuid,Gorm对该包的UUID类型有原生支持 - PlanetScale的MySQL环境完全兼容
uuid()函数,无需额外配置扩展
内容的提问来源于stack exchange,提问作者Kristófer Fannar Björnsson
相关产品推荐
相关产品推荐

