结构类型(struct)
- 为了将分散的零件组成一个完整的结构体,Go 提供了 struct 类型。
- struct 允许你将不同类型的东西组合在一起。
- 声明结构
package mainimport "fmt"func main() { var curiosity struct { lat float64 long float64 } curiosity.lat = -4.5895 curiosity.long = 137.4417 fmt.Println(curiosity.lat, curiosity.long) fmt.Println(curiosity)}
通过类型复用结构体
package mainimport "fmt"func main() { type location struct { lat float64 long float64 } var spirit location spirit.lat = -14.5684 spirit.long = 175.472636 var opportunity location opportunity.lat = -1.9462 opportunity.long = 354.4734 fmt.Println(spirit, opportunity)}
通过复合字面值初始化 struct
package mainimport "fmt"func main() { type location struct { lat, long float64 } opportunity := location{lat: -1.9462, long: 354.4734} fmt.Println(opportunity) insight := location{lat: 4.5, long: 135.9} fmt.Println(insight) spirit := location{-14.5684, 175.472636} fmt.Println(spirit) curiosity := location{-4.5895, 137.4417} fmt.Printf("%v\n", curiosity) fmt.Printf("%+v\n", curiosity)}
- 按字段定义的顺序进行初始化(例子 21.4)
- 打印 struct(例子 21.5)
- %v,打印出 {-4.5895 137.4417}
- %+v,打印出 {lat:-4.5895 long:137.4417}
struct 的复制
package mainimport "fmt"func main() { type location struct { lat float64 long float64 } bradbury := location{-4.5895, 137.4417} curiosity := bradbury curiosity.long += 0.0106 fmt.Println(bradbury, curiosity)}
由结构体组成的 slice
package mainfunc main() { lats := []float64{-4.5895, -14.5684, -1.9462} longs := []float64{137.4417, 175.472636, 354.4734} _ = lats _ = longs type location struct { name string lat float64 long float64 } locations := []location{ {name: "Bradbury Landing", lat: -4.5895, long: 137.4417}, {name: "Columbia Memorial Station", lat: -14.5684, long: 175.472636}, {name: "Challenger Memorial Station", lat: -1.9462, long: 354.4734}, } _ = locations}
将 struct 编码为 JSON
- JSON(JavaScript Object Notation,JavaScript 对象表示法)
- 常用于 Web API
- json 包的 Marshal 函数可以将 struct 中的数据转化为 JSON 格式。
- Marshal 函数只会对 struct 中被导出的字段进行编码。
package mainimport ( "encoding/json" "fmt" "os")func main() { type location struct { Lat, Long float64 } curiosity := location{-4.5895, 137.4417} bytes, err := json.Marshal(curiosity) exitOnError(err) fmt.Println(string(bytes))}// exitOnError prints any errors and exits.func exitOnError(err error) { if err != nil { fmt.Println(err) os.Exit(1) }}
使用 struct 标签来自定义 JSON
- Go 语言中的 json 包要求 struct 中的字段必须以大写字母开头,类似 CamelCase 驼峰型命名规范。
- 但有时候我们需要 snake_case 蛇形命名规范,那么该怎么办?
- 可以为字段注明标签,使得 json 包在进行编码的时候能够按照标签里的样式修改字段名。
package mainimport ( "encoding/json" "fmt" "os")func main() { type location struct { Lat float64 `json:"latitude"` Long float64 `json:"longitude"` } curiosity := location{-4.5895, 137.4417} bytes, err := json.Marshal(curiosity) exitOnError(err) fmt.Println(string(bytes))}// exitOnError prints any errors and exitsfunc exitOnError(err error) { if err != nil { fmt.Println(err) os.Exit(1) }}
作业题
- 编写一个程序:
- 能够以 JSON 格式打印出 例子 21.8 中 3 台 探测器的着陆点。
- 被打印的 JSON 数据必须包含每个着陆点的名称,并使用例子 21.10 中展示的 struct 标签特性。
- 请使用 json 包中的 MarshalIndent 函数让打印输出变得更加美观和易读。
package mainimport ( "encoding/json" "fmt" "os")func main() { type location struct { Name string `json:"name"` Lat float64 `json:"latitude"` Long float64 `json:"longitude"` } locations := []location{ {Name: "Bradbury Landing", Lat: -4.5895, Long: 137.4417}, {Name: "Columbia Memorial Station", Lat: -14.5684, Long: 175.472636}, {Name: "Challenger Memorial Station", Lat: -1.9462, Long: 354.4734}, } bytes, err := json.MarshalIndent(locations, "", " ") if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println(string(bytes))}