Go语言结构体(struct)详解:定义、使用与JSON编码

Go语言结构体(struct)详解:定义、使用与JSON编码在Go语言中,结构体(struct)是一种非常重要的复合数据类型,它允许开发者将不同类型的数据组合在一起,形成更复杂的对象结构。结构体不仅用于数据的组织和管理,还广泛应用于网络编程、Web开发和数据序列化等领域。掌握Go语言中的结构体,不

Go语言结构体(struct)详解:定义、使用与JSON编码

在Go语言中,结构体(struct)是一种非常重要的复合数据类型,它允许开发者将不同类型的数据组合在一起,形成更复杂的对象结构。结构体不仅用于数据的组织和管理,还广泛应用于网络编程、Web开发和数据序列化等领域。掌握Go语言中的结构体,不仅能提升代码的可读性与可维护性,还能帮助开发者更高效地构建应用程序。本文将详细介绍Go语言结构体的定义、使用方式,以及如何将结构体数据转换为JSON格式,帮助你在实际开发中灵活运用。

本文深入探讨了Go语言中的结构体(struct)类型,首先介绍了结构体的基本概念和声明方式,然后通过实例讲解了如何初始化、复制和传递结构体数据。接着,我们将重点讨论如何通过结构体编码和解码JSON数据,包括如何使用Go的json包进行数据序列化,以及如何通过结构体标签自定义JSON字段名的映射。最后,文中还提供了一些练习题,帮助读者巩固所学知识。

结构体

结构类型(struct)

  • 为了将分散的零件组成一个完整的结构体,Go提供了struct类型。
  • struct允许你将不同类型的东西组合在一起。
  • 声明结构
package main

func distance(lat1, long1, lat2, long2 float64) float64 {
  return 0.0
}

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)
}

小测试

  1. 与独立的变量相比,使用struct的优势是什么?
  2. 上例中,如果curiosity有一个海拔(altitude)字段,那么你如何给它赋值为-4400?

通过类型复用结构体

package main

func distance(loc1, loc2 location) dis {
  return dis{0.0, 0.0}
}

type location struct {
  lat float64
  long float64
}

// type dis location

type dis struct {
  lat float64
  long float64
}

func main() {
  //var curiosity struct {
   // lat float64
  //  long float64
  //}

  //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)
}

小测试

  • 修改上面例子的代码,改用location类型表示好奇号火星探测器的位置

通过复合字面值初始化struct

  • 两种形式:
    • 通过成对的字段和值进行初始化
    • 按字段定义的顺序进行初始化
package main

import "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)
}
  • 打印struct
pakcage main

import "fmt"

func main() {
  type location struct {
    lat, long float64
  }

  curiosity := location{-4.5859, 137.4417}
  fmt.Printf("%v\n", curiosity)
  fmt.Printf("%+v\n", curiosity)
}
  • %v,打印出{-4.5895 137.4417}
  • %+v,打印出{lat:-4.5895 long:137.4417}

小测试

  • 与只给定值的初始化方式相比,成对给定字段和值的初始化方式有哪些优势?

struct的复制

pakcage main

import "fmt"

func main() {
  type location struct {
    lat, long float64
  }

  bradbury := location{-4.5859, 137.4417}
  curiosity := bradbury

  curiosity.long += 0.0106

  fmt.Println(bradbury, curiosity)
}

小测试

  • 如果将curiosity变量传递给函数,并在函数中对lat和long字段进行修改,那么调用者是否会看到这些变化?

由结构体组成的slice

package main

import "fmt"

func main() {
  type location struct {
    name string
    lat float64
    long float64
  }

  lats := []float64{-4.5859, -14.5684, -1.9462}
  longs := []float64{137.4417, 175.472636, 354.4734}

  locations := []location{
    {name: "Bradbury Landing", lat: -4.5859, long: 137.4417},
    {name: "Columbia Memorial Station", lat: -14.5684, long: 175.472636},
    {name: "Challenger Memorial Station", lat: -1.9462, long: 354.4734},
  }

  fmt.Println(lats, longs, locations)
}

小测试

  • 使用多个相互关联的slice有什么坏处?

将struct编码为JSON

  • JSON(JavaScript Object Notation,JavaScript对象表示法)

  • 常用于Web API

  • json包的Marshal函数可以将struct中的数据转化为JSON格式。

package main

import (
  "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)
  }
}
  • Marshal函数只会对struct中被导出的字段进行编码。

小测试

  • JSON代表什么意思?

使用struct标签来自定义JSON

  • Go语言中的json包要求struct中的字段必须以大写字母开头,类似CamelCase驼峰型命名规范。

  • 但有时候我们需要snake_case蛇形命名规范,那么该怎么办?

  • 可以为字段注明标签,使得json包在进行编码的时候能够按照标签里的样式修改字段名。

package main

import (
  "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 exits.
func exitOnError(err error) {
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
}

小测试

  • 为什么在编码JSON数据的时候,Lat和Long字段必须以大写字母开头?

作业题

  • 编写一个程序:
    • 能够以JSON格式打印出 上面例子中3台 探测器的着陆点。
    • 被打印的JSON数据必须包含每个着陆点的名称,并使用上面例子中展示的struct标签特性。
    • 请使用json包中的MarshalIndent函数让打印输出变得更加美观和易读。

总结

Go语言中的结构体是组织和管理复杂数据的核心工具,理解其定义、初始化、传递和复制方式对开发高效、可维护的代码至关重要。通过结构体与JSON的结合,我们可以更方便地与外部系统进行数据交换。在本文中,我们不仅展示了如何在Go中定义和使用结构体,还介绍了如何通过结构体标签进行JSON的自定义映射,极大地方便了数据的序列化与反序列化。掌握这些基本技巧,将为你的Go语言编程之路打下坚实的基础。

  • 原创
  • 学分: 2
  • 分类: Go
  • 标签:
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
该文章收录于 Go 语言
3 订阅 20 篇文章

0 条评论

请先 登录 后评论
寻月隐君
寻月隐君
0x89EE...a439
不要放弃,如果你喜欢这件事,就不要放弃。如果你不喜欢,那这也不好,因为一个人不应该做自己不喜欢的事。