结构类型(struct)

  • 为了将分散的零件组成一个完整的结构体,Go 提供了 struct 类型。
  • struct 允许你将不同类型的东西组合在一起。
  • 声明结构
  1. package main
  2. import "fmt"
  3. func main() {
  4. var curiosity struct {
  5. lat float64
  6. long float64
  7. }
  8. curiosity.lat = -4.5895
  9. curiosity.long = 137.4417
  10. fmt.Println(curiosity.lat, curiosity.long)
  11. fmt.Println(curiosity)
  12. }

通过类型复用结构体

  1. package main
  2. import "fmt"
  3. func main() {
  4. type location struct {
  5. lat float64
  6. long float64
  7. }
  8. var spirit location
  9. spirit.lat = -14.5684
  10. spirit.long = 175.472636
  11. var opportunity location
  12. opportunity.lat = -1.9462
  13. opportunity.long = 354.4734
  14. fmt.Println(spirit, opportunity)
  15. }

通过复合字面值初始化 struct

  • 两种形式:
    • 通过成对的字段和值进行初始化
  1. package main
  2. import "fmt"
  3. func main() {
  4. type location struct {
  5. lat, long float64
  6. }
  7. opportunity := location{lat: -1.9462, long: 354.4734}
  8. fmt.Println(opportunity)
  9. insight := location{lat: 4.5, long: 135.9}
  10. fmt.Println(insight)
  11. spirit := location{-14.5684, 175.472636}
  12. fmt.Println(spirit)
  13. curiosity := location{-4.5895, 137.4417}
  14. fmt.Printf("%v\n", curiosity)
  15. fmt.Printf("%+v\n", curiosity)
  16. }
  1. - 按字段定义的顺序进行初始化(例子 21.4
  • 打印 struct(例子 21.5)
    • %v,打印出 {-4.5895 137.4417}
    • %+v,打印出 {lat:-4.5895 long:137.4417}

struct 的复制

  1. package main
  2. import "fmt"
  3. func main() {
  4. type location struct {
  5. lat float64
  6. long float64
  7. }
  8. bradbury := location{-4.5895, 137.4417}
  9. curiosity := bradbury
  10. curiosity.long += 0.0106
  11. fmt.Println(bradbury, curiosity)
  12. }

由结构体组成的 slice

  1. package main
  2. func main() {
  3. lats := []float64{-4.5895, -14.5684, -1.9462}
  4. longs := []float64{137.4417, 175.472636, 354.4734}
  5. _ = lats
  6. _ = longs
  7. type location struct {
  8. name string
  9. lat float64
  10. long float64
  11. }
  12. locations := []location{
  13. {name: "Bradbury Landing", lat: -4.5895, long: 137.4417},
  14. {name: "Columbia Memorial Station", lat: -14.5684, long: 175.472636},
  15. {name: "Challenger Memorial Station", lat: -1.9462, long: 354.4734},
  16. }
  17. _ = locations
  18. }

将 struct 编码为 JSON

  • JSON(JavaScript Object Notation,JavaScript 对象表示法)
  • 常用于 Web API
  • json 包的 Marshal 函数可以将 struct 中的数据转化为 JSON 格式。
  • Marshal 函数只会对 struct 中被导出的字段进行编码。
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. type location struct {
  9. Lat, Long float64
  10. }
  11. curiosity := location{-4.5895, 137.4417}
  12. bytes, err := json.Marshal(curiosity)
  13. exitOnError(err)
  14. fmt.Println(string(bytes))
  15. }
  16. // exitOnError prints any errors and exits.
  17. func exitOnError(err error) {
  18. if err != nil {
  19. fmt.Println(err)
  20. os.Exit(1)
  21. }
  22. }

使用 struct 标签来自定义 JSON

  • Go 语言中的 json 包要求 struct 中的字段必须以大写字母开头,类似 CamelCase 驼峰型命名规范。
  • 但有时候我们需要 snake_case 蛇形命名规范,那么该怎么办?
  • 可以为字段注明标签,使得 json 包在进行编码的时候能够按照标签里的样式修改字段名。
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. type location struct {
  9. Lat float64 `json:"latitude"`
  10. Long float64 `json:"longitude"`
  11. }
  12. curiosity := location{-4.5895, 137.4417}
  13. bytes, err := json.Marshal(curiosity)
  14. exitOnError(err)
  15. fmt.Println(string(bytes))
  16. }
  17. // exitOnError prints any errors and exits
  18. func exitOnError(err error) {
  19. if err != nil {
  20. fmt.Println(err)
  21. os.Exit(1)
  22. }
  23. }

作业题

  • 编写一个程序:
    • 能够以 JSON 格式打印出 例子 21.8 中 3 台 探测器的着陆点。
    • 被打印的 JSON 数据必须包含每个着陆点的名称,并使用例子 21.10 中展示的 struct 标签特性。
    • 请使用 json 包中的 MarshalIndent 函数让打印输出变得更加美观和易读。
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. type location struct {
  9. Name string `json:"name"`
  10. Lat float64 `json:"latitude"`
  11. Long float64 `json:"longitude"`
  12. }
  13. locations := []location{
  14. {Name: "Bradbury Landing", Lat: -4.5895, Long: 137.4417},
  15. {Name: "Columbia Memorial Station", Lat: -14.5684, Long: 175.472636},
  16. {Name: "Challenger Memorial Station", Lat: -1.9462, Long: 354.4734},
  17. }
  18. bytes, err := json.MarshalIndent(locations, "", " ")
  19. if err != nil {
  20. fmt.Println(err)
  21. os.Exit(1)
  22. }
  23. fmt.Println(string(bytes))
  24. }