摘要
本文主要记录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





暂无评论内容