摘要
本文主要记录golang
的常用代码片段和特殊的代码写法。
内容
var _
检测接口中的方法是否被定义
可以在结构体未被使用前,让编译器检查其是否实现了接口所需的所有方法。
代码
// 检查 NokiaPhone 是否实现了 Phone 接口所需的所有方法,两种写法都可以。
var _ Phone = (*NokiaPhone)(nil)
var _ Phone = &NokiaPhone{}
type Phone interface {
call()
}
type NokiaPhone struct {
}
func (nokiaPhone NokiaPhone) call() {
fmt.Println("I am Nokia, I can call you!")
}
说明
- _ 为了避免变量未使用编译的时候报错
- _ 的类型为
NokiaPhone
。
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)
}
注意:里面空值处理的部分是必须的,如果数据库当时是空值,传入Scan
的value
是一个string
类型而非[]byte
。转义时会出错。
结构体覆盖
可用于Map
和结构体的转换,以及复制结构体或Map
。
func StructCover(in interface{}, to interface{}) error {
b, err := json.Marshal(&in)
if err != nil {
return err
}
_ = json.Unmarshal(b, to)
return nil
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
广告
暂无评论内容