Golang匿名结构体的使用场景
结构体基础
结构体 (struct) 多个不同类型的字段 组成一种复合类型 按声明时的字段顺序初始化
type user struct {
name string
age byte
}
user := user{"Tom", 2}
定义匿名结构体 没有 type 关键字 与其他定义类型的变量一样
在函数外部 需在结构体变量前加上 var 关键字
在函数内部 可省略 var 关键字
// 在函数外部定义匿名结构体并赋值给
var config struct {
APIKey string
OAuthConfig oauth.Config
}
datadata := struct {// 定义并初始化并赋值
Title string
Users []*User
}{title,users}
匿名结构体使用场景
组织全局变量
属于同一类的全局变量可通过匿名结构体组织在一起var config struct {
APIKey string
OAuthConfig oauth.Config
}
config.APIKey = "BADC0C0A"
数据模版
后端把 数据组织成 前端需要的格式传给渲染模版package main
import (
"html/template"
"net/http"
"strings"
)
type Paste struct {
Expiration string
Content []byte
UUID string
}
func pasteHandler(w http.ResponseWriter, r *http.Request) {
paste_id := strings.TrimPrefix(r.URL.Path, "/paste")
paste := &Paste{UUID: paste_id}
keep_alive := false
burn_after_reading := false
data := struct {
Paste *Paste
KeepAlive bool
BurnAfterReading bool
} {paste,keep_alive,burn_after_reading, }
t, _ := template.ParseFiles("templates/paste.html")
t.Execute(w, data)
}
匿名函授定义并初始化之后赋值给 data 变量 除了把 Paste 结构体对象的值传给前端之外 还额外添加了必要的字段
前端需要后端返回 标志变量 作为判断条件是否显示某一块内容
Expiration: {{ .Paste.Expiration }}
UUID: {{ .Paste.UUID}}
{{ if .BurnAfterReading }}
BurnAfterReading: True{{ else }}
BurnAfterReading: False{{ end }}
测试案例数据
测试代码 常用到匿名结构体生成用例的输入输出为了覆盖 测试维度 常结合切片 构成测试样例 尽可能 覆盖所有可能发生情况
var indexRuneTests = []struct {
s string
rune rune out int}{
{"a A x", 'A', 2},
{"some_text=some_value", '=', 9},
{"a", 'a', 3},
{"ab", '', 4},
}
嵌入式锁
(Embedded lock)var hits struct {
sync.Mutex
n int}
hits.Lock()
hits.n++
hits.Unlock()
案例 手机有屏幕 电池 指纹识别等信息
将这些信息填充为 JSON 格式的数据
如果需要选择性地分离 JSON 中的数据则较为麻烦
Go 匿名结构体 方便地完成这个操作
package main
import (
"encoding/json"
"fmt"
)
type Screen01 struct {//定义手机屏幕
Size float64 //屏幕尺寸
ResX, ResY int //屏幕分辨率 水平 垂直
}
type Battery struct {//定义电池容量
Capacity string
}
func getJsonData() []byte {//返回json数据
tempData := struct {//tempData 接收匿名结构体(匿名结构体使 数据的结构 灵活)
Screen01
Battery
HashTouchId bool // 是否有指纹识别
}{
Screen01: Screen01{Size: 12, ResX: 36, ResY: 36},
Battery: Battery{"6000毫安"},
HashTouchId: true,
}
jsonData, _ := json.Marshal(tempData) //将数据转换为json
return jsonData
}
func main() {
jsonData := getJsonData() //获取json数据
fmt.Println(jsonData)
fmt.Println("=解析 分离 出的数据是=")
allData := struct {//自定义匿名结构体 解析(分离)全部数据
Screen01
Battery
HashTouchId bool
}{}
json.Unmarshal(jsonData, &allData)
fmt.Println("解析(分离)全部结构为:", allData)
screenBattery := struct {//自定义匿名结构体 通过json数据 解析分离对应的结构(可以是部分结构)
Screen01
Battery
}{}
json.Unmarshal(jsonData, &screenBattery) //注意:此处只能为结构体指针(一般参数为interface{} 都采用地址引用(即地址传递))
fmt.Println("解析(分离)部分结构:", screenBattery)
batteryTouch := struct { //自定义匿名结构体 解析 分离 部分结构
Battery
isTouch bool
}{}
json.Unmarshal(jsonData, &batteryTouch)
fmt.Println("解析(分离)部分结构:", batteryTouch)
temp1 := struct {//自定义匿名结构体 解析 分离 部分不存在的结构
Battery
Detail struct {
Name string
Price uint16
}
}{}
json.Unmarshal(jsonData, &temp1)
fmt.Println("解析(分离)部分不存在的结构", temp1)
temp2 := struct {//自定义匿名结构体 解析(分离)完全不存在的结构
User string
Price uint16
}{}
json.Unmarshal(jsonData, &temp2)
fmt.Println("解析(分离)完全不存在的结构:", temp2)
}
匿名结构体 组合不同类型的数据 处理数据更灵活
在需要将多个变量 类型数据组合应用的场景 匿名结构体是一个不错的选择
json.Unmarshal(data []byte, v interface{})
参数 v 只能为结构体指针(一般参数为interface{} 都采用地址引用(即地址传递))
定义数据结构
首先 定义手机的各种数据结构体 如屏幕和电池type Screen struct {// 定义手机屏幕
Size float32 // 屏幕尺寸
ResX, ResY int // 屏幕水平和垂直分辨率
}
type Battery struct {// 定义电池
Capacity int // 容量
}
定义了屏幕结构体和电池结构体 分别描述屏幕和电池的各种细节参数
准备手机数据结构 填充数据 将数据序列化为 JSON 格式的字节数组
func genJsonData() []byte {// 生成JSON数据
raw := &struct {// 完整数据结构
Screen
Battery
HasTouchID bool // 序列化时添加的字段:是否有指纹识别
}{Screen: Screen{ Size: 5.5,ResX: 1920,ResY: 1080,},
Battery: Battery{ 2910, },
HasTouchID: true,// 是否有指纹识别
}
jsonData, _ := json.Marshal(raw) // 将数据序列化为JSON
return jsonData
}
分离JSON数据
调用 genJsonData 获得 JSON 数据 将需要的字段填充到匿名结构体实例中 通过 json.Unmarshal 反序列化 JSON 数据达成分离 JSON 数据效果func main() {
jsonData := genJsonData() // 生成一段JSON数据
fmt.Println(string(jsonData))// 只需要屏幕和指纹识别信息的结构和实例
screenAndTouch := struct {
Screen
HasTouchID bool
}{}
// 反序列化到screenAndTouch中
json.Unmarshal(jsonData, &screenAndTouch)
// 输出screenAndTouch的详细结构
fmt.Printf("%+v\n", screenAndTouch)
// 只需要电池和指纹识别信息的结构和实例
batteryAndTouch := struct {
Battery
HasTouchID bool
}{}
// 反序列化到batteryAndTouch
json.Unmarshal(jsonData, &batteryAndTouch)
// 输出screenAndTouch的详细结构
fmt.Printf("%+v\n", batteryAndTouch)
}
尊贵的董事大人
英文标题不为空时 视为本栏投稿
需要关键字 描述 英文标题