关于解决 go 存到数据库中自定义类型为null 取出来却是空结构体(0值)问题

关于解决 go 存到数据库中自定义类型为null 取出来却是空结构体(0值)问题

在我存储Message表的时候,我定义Message为空,存到数据库中也是为null,但是读取出来的时候,却变成了一个初始化为空的结构体,并不是nil。

Test:

package handler

import (
	"database/sql/driver"
	"encoding/json"
	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"
	"im_server/common/models"
	"im_server/core"
	"testing"
)

type Message struct {
    // 此MODEL是自定义结构体
	models.MODEL
	Content    string      `json:"content"`
	SystemHint *SystemHint `json:"system_hint"`
}

// SystemHint 系统提示
type SystemHint struct {
	Type int8 `json:"type"` // 系统违规提示 1-涉黄 2-涉恐 3-涉证 4-不正当言论
}

// Scan 处理从数据库取出的数据
func (t *SystemHint) Scan(value any) error {
	return json.Unmarshal(value.([]byte), t)
}

// Value 处理存入数据库的数据
func (t *SystemHint) Value() (driver.Value, error) {
	b, err := json.Marshal(t)
	return string(b), err
}

func MigrateTable(db *gorm.DB) {
	err := db.AutoMigrate(&Message{})
	if err != nil {
		logx.Error(err)
		return
	}
	err = db.Create(&Message{}).Error
	if err != nil {
		logx.Error(err)
	}
}

func TestMul(t *testing.T) {
    // InitGorm是自定义连接函数
	db := core.InitGorm("root:1234@tcp(127.0.0.1:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local")
	MigrateTable(db)

	message := Message{}
	logx.Infof("message: %+v", message)
    
	err := db.Take(&message, 1).Error
	logx.Infof("message: %+v", message)
	if err != nil {
		logx.Errorf("err: %+v", err)
	}

}

image-20241201130835191

随后发现,在我将数据库中的SystemHint字段的null删除为空之后,读取出来的SystemHint正确的变成了nil,说明自定义的SystemHint的Scan方法如果遇到的是null,就会自动转换为0值。那么如果仍然需要nil值,就需要在Value方法中变化。

我发现,在SystemHint的成员函数中,将t *SystemHint的结构体指针更改为结构体t SystemHint,如果存储的SystemHint为nil,那么存到数据库中就不会变成null,而是为空,这样Scan读取出来的时候,就是nil

// Value 处理存入数据库的数据
func (t SystemHint) Value() (driver.Value, error) {
	b, err := json.Marshal(t)
	return string(b), err
}

运行之后数据库结果如下:

image-20241201131532323

日志如下:

image-20241201131747122

posted @ 2025-03-28 19:22  小依昂阳  阅读(28)  评论(0)    收藏  举报