结构类型(struct)
- 为了将分散的零件组成一个完整的结构体,Go 提供了 struct 类型。
- struct 允许你将不同类型的东西组合在一起。
- 声明结构
package main
import "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 main
import "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 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)
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 main
import "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 main
func 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 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)
}
}
使用 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 格式打印出 例子 21.8 中 3 台 探测器的着陆点。
- 被打印的 JSON 数据必须包含每个着陆点的名称,并使用例子 21.10 中展示的 struct 标签特性。
- 请使用 json 包中的 MarshalIndent 函数让打印输出变得更加美观和易读。
package main
import (
"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))
}