gen 生成代码 needDefaultTag 空指针异常

92 阅读1分钟

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()