Go语言 如何定义自定义sql类型枚举字段

dm7nw8vv  于 2023-05-04  发布在  Go
关注(0)|答案(1)|浏览(219)

我想像这样定义自定义sql类型enum

package db

import (
    "database/sql/driver"
    "github.com/spf13/cast"
)

type Enum int64

func (e Enum) Value() (driver.Value, error) {
    return int64(e), nil
}

func (e *Enum) Scan(v any) error {
    *e = Enum(cast.ToInt64(v))
    return nil
}

我想使用以下内容:

package db_test

import (
    "db"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
    "testing"
)

type StatusEnum = db.Enum

const (
    StatusEnumEnable StatusEnum = iota
    StatusEnumDisable
)

// this is error because this type alias can not define new method
//func (e *StatusEnum) String() string{
//  if v,ok := StatusEnumMap[*e];ok{
//      return v
//  }
//  return "unknown"
//}

var StatusEnumMap = map[StatusEnum]string{
    StatusEnumEnable:  "Enable",
    StatusEnumDisable: "Disable",
}

type module struct {
    Status StatusEnum
}

func TestEnum(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open(":memory:"))

    db.AutoMigrate(&module{})

    db.Model(&module{}).Create(&module{Status: StatusEnumDisable})

    var out *module
    // SELECT * FROM `modules` WHERE status=1 ORDER BY `modules`.`status` LIMIT 1
    db.Debug().Model(&module{}).Where("status=?", StatusEnumDisable).First(&out)

    t.Log(out)
    t.Log(StatusEnumMap[out.Status])
    //t.Log(out.Status.String())
}

现在,当我需要字符串格式时,我会像这样使用StatusEnumMap[EnumValue]。我认为value.String()更优雅和简单。fmt也可以打印字符串而不是数字。
如何更好地实现此功能?谢谢你的建议。

gwbalxhn

gwbalxhn1#

如果底层类型是int64,似乎不需要实现ValuerScanner接口。如果是这样,则不需要Enum类型。下面的示例在没有Enum的情况下工作:

注意:我稍微修改了一下你的demo,在StatusEnum类型上实现了Stringer接口,而不是*StatusEnum

package db_test

import (
    "testing"

    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

type StatusEnum int64

const (
    StatusEnumEnable StatusEnum = iota
    StatusEnumDisable
)

var StatusEnumMap = map[StatusEnum]string{
    StatusEnumEnable:  "Enable",
    StatusEnumDisable: "Disable",
}

func (e StatusEnum) String() string {
    if v, ok := StatusEnumMap[e]; ok {
        return v
    }
    return "unknown"
}

type module struct {
    Status StatusEnum
}

func TestEnum(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open(":memory:"))

    db.AutoMigrate(&module{})

    db.Model(&module{}).Create(&module{Status: StatusEnumDisable})

    var out *module
    // SELECT * FROM `modules` WHERE status=1 ORDER BY `modules`.`status` LIMIT 1
    db.Debug().Model(&module{}).Where("status=?", StatusEnumDisable).First(&out)

    t.Log(out)
    t.Logf("status value: %d, status string: %s", out.Status, out.Status)
}

输出为:

&{Disable}
status value: 1, status string: Disable

请注意,现在第一个是&{Disable}。之前是&{1}

相关问题