一:Json类型
Info保存到数据库时,通过Value()转化为json,读取出来的时候 json字符串自动转成结构体Info
type Info struct {
Status string `json:"status"`
Addr string `json:"addr"`
Age int `json:"age"`
}
// Scan 从数据库中读取出来
func (i *Info) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
}
info := Info{}
err := json.Unmarshal(bytes, &info)
*i = info
return err
}
// Value 存入数据库
func (i Info) Value() (driver.Value, error) {
return json.Marshal(i)
}
//改正指针接受者 确实不行
//func (i *Info) Value() (driver.Value, error) {
// return json.Marshal(i)
//}
type User struct {
ID uint
Name string
Info Info `gorm:"type:string"`
}
Scan和Value方法,一个是指针方法一个是值方法
二:数组类型
三:枚举
type Host struct {
ID uint
Name string
Status string
}
func main() {
host := Host{}
if host.Status == "Running" {
fmt.Println("在线")
}
if host.Status == "Except" {
fmt.Println("异常")
}
if host.Status == "OffLine" {
fmt.Println("离线")
}
}
字符串硬编码
type Host struct {
ID uint
Name string
Status string
}
const (
Running = "Running"
Except = "Except"
OffLine = "OffLine"
)
func main() {
host := Host{}
if host.Status == Running {
fmt.Println("在线")
}
if host.Status == Except {
fmt.Println("异常")
}
if host.Status == OffLine {
fmt.Println("离线")
}
}
type Host struct {
ID uint
Name string
Status int
}
const (
Running = 1
Except = 2
OffLine = 3
)
func main() {
host := Host{}
if host.Status == Running {
fmt.Println("在线")
}
if host.Status == Except {
fmt.Println("异常")
}
if host.Status == OffLine {
fmt.Println("离线")
}
}
但是,如果返回数据给前端,前端接收到的状态就是数字,不过问题不大,前端反正都要搞字符映射的,因为要做颜色差异显示。
但是这并不是后端偷懒的理由 于是我们想到,在json序列化的时候,根据映射转换回去
type Host struct {
ID uint `json:"id"`
Name string `json:"name"`
Status int `json:"status"`
}
func (h Host) MarshalJSON() ([]byte, error) {
var status string
switch h.Status {
case Running:
status = "Running"
case Except:
status = "Except"
case OffLine :
status = "OffLine"
}
return json.Marshal(&struct {
ID uint `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
}{
ID: h.ID,
Name: h.Name,
Status: status,
})
}
const (
Running = 1
Except = 2
OffLine = 3
)
func main() {
host := Host{1, "枫枫", Running}
data, _ := json.Marshal(host)
fmt.Println(string(data)) // {"id":1,"name":"枫枫","status":"Running"}
}
这样写确实可以实现我们的需求,但是根本就不够通用,凡是用到枚举,都得给这个Struct实现MarshalJSON
方法
类型别名
type Status int
func (status Status) MarshalJSON() ([]byte, error) {
var str string
switch status {
case Running:
str = "Running"
case Except:
str = "Except"
case OffLine:
str = "Status"
}
return json.Marshal(str)
}
type Host struct {
ID uint `json:"id"`
Name string `json:"name"`
Status Status `json:"status"`
}
const (
Running Status = 1
Except Status = 2
OffLine Status = 3
)
func main() {
host := Host{1, "枫枫", Running}
data, _ := json.Marshal(host)
fmt.Println(string(data)) // {"id":1,"name":"枫枫","status":"Running"}
}
嗯,代码简洁了不少,在使用层面已经没有问题了
但是,这个结构体怎么表示数据库中的字段呢?
golang中没有枚举
我们只能自己通过逻辑实现枚