gen 生成代码 needDefaultTag 空指针异常
已知受影响版本:gen@v0.3.26 使用 goose 迁移 sqlite 数据库时产生报错。
1. 异常分析
具体issue: github.com/go-gorm/gen…
报错代码如下:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xa8 pc=0x2390645]
goroutine 1 [running]:
gorm.io/gen/internal/model.(*Column).needDefaultTag(0xc00056c280, {0xc0002a74bd, 0x10})
/Users/.../go/pkg/mod/gorm.io/gen@v0.3.26/internal/model/tbl_column.go:131 +0x45
定位到 tbl_column.go:131,发现即 switch c.ScanType().Kind() 处出现空指针异常。其内容如下:
// needDefaultTag check if default tag needed
func (c *Column) needDefaultTag(defaultTagValue string) bool {
if defaultTagValue == "" {
return false
}
switch c.ScanType().Kind() {
case reflect.Bool:
return defaultTagValue != "false"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
return defaultTagValue != "0"
case reflect.String:
return defaultTagValue != ""
case reflect.Struct:
return strings.Trim(defaultTagValue, "'0:-") != ""
}
return c.Name() != "created_at" && c.Name() != "updated_at"
}
最终经过排查,元凶是我使用 goose 迁移数据库时产生的 goose_db_version 表导致的。
2. 解决方案
使用 WithTableNameStrategy 方法跳过goose_db_version 表,代码如下:
g.WithTableNameStrategy(func(tableName string) (targetTableName string) {
if strings.HasPrefix(tableName, "sqlite") { // Just return an empty string and the table will be ignored.
return ""
}
if strings.HasPrefix(tableName, "goose") { // Just return an empty string and the table will be ignored.
return ""
}
return tableName
})
g.ApplyBasic(
// Generate structs from all tables of current database
g.GenerateAllTable()...,
)
// Generate the code
g.Execute()