Golang 常用代码片段

  • A+
所属分类:编程开发

摘要

本文主要记录常用的golang代码片段。

分析

Gorm 自定义JSON Model

可以将自定义类型以Json编码的方式存入数据库文本类型中。使用ORM时,和普通类型没有区别。

第一种写法

// JSONMap
type JSONMap map[string]string

// Scan Scanner
func (t *JSONMap) Scan(value interface{}) error {
    if value == nil {
        return nil
    }

    v, ok := value.(string)
    if !ok {
        return fmt.Errorf("value is not string, value: %v", value)
    }

    // if empty
    if len(v) == 0 {
        b = "{}"
    }

    return json.Unmarshal([]byte(v), t)
}

// Value Valuer
func (t JSONMap) Value() (driver.Value, error) {
    if t == nil {
        return nil, nil
    }
    bytes, err := json.Marshal(t)
    if err != nil {
        return nil, err
    }
    // return string type
    return string(bytes), nil
}

注意: 在Value函数中,如果直接返回bytes,会导致查询时Scan传入的value[]byte类型而报错。

第二种写法

第一种写法中,我们会把数据转换成string存入数据库。但我们发现json函数转换时支持的数据结类型是[]bytes
下面的写法可以避免多余的转换。

// JSONMap
type JSONMap map[string]string

// Scan Scanner
func (t *JSONMap) Scan(value interface{}) error {
    if value == nil {
        return nil
    }

    // empty value
    if reflect.ValueOf(value).Len() == 0 {
        *t = map[string]string{}
        return nil
    }

    return json.Unmarshal(reflect.ValueOf(value).Bytes(), t)
}

// Value Valuer
func (t JSONMap) Value() (driver.Value, error) {
    if t == nil {
        return nil, nil
    }
    return json.Marshal(t)
}

注意:里面空值处理的部分是必须的,如果数据库当时是空值,传入Scanvalue是一个string类型而非[]byte。转义时会出错。

结构体覆盖

func StructCover(in interface{}, to interface{}) error {
    b, err := json.Marshal(&in)
    if err != nil {
        return err
    }

    _ = json.Unmarshal(b, to)
    return nil
}

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: