golang结构体

结构体

结构体是将零个或多个任意类型命名变量组合在一起的聚合数据类型。每个变量叫做结构体的成员,示例如下:


type Employee struct {
    ID int
    Name string
    Address string
    DoB time.Time
    Position string
    Salary int
    ManagerID int
}

结构体成员变量通常一行写一个,变量的名称在类型的前面。但是相同类型的连续成员变量可以写在一行,如Name和Address:

type Employee struct {
    ID int
    Name, Address string
    DoB time.Time
    Position string
    Salary int
    ManagerID int
}

成员变量的顺序对结构体的同一性很重要,如果将也是字符串类型的Position和Name,Address组合在了一起,或交换了Name和Address的顺序,那么就定义了一个不同的结构体。一般来讲,只组合相关的成员变量。

需要注意的点

命名结构体类型,假设名称为s,不可以定义一个拥有相同结构体类型s的成员变量,也就是一个聚合类型不可以包含它自己(同样的限制对数组也使用).但是s中可以定义一个s的指针类型,即*s。这样就可以创建一些递归数据结构,如链表和树。

空结构体

没有任何成员变量的结构体称为空结构体,写做struct{}.它没有长度,也不携带任何信息,但有时会很有用。有一些go程序员使用它来代替被当做集合使用的map中的布尔值,来强调只有键是有用的,但这种方式节约的内存很少且语法复杂,所以一般尽量避免这样使用

seen := make(map[string]struct{}) // 字符串集合
// ...
if _, ok := seen[s];!ok {
    seen[s] = struct{}{}
    // ...首次出现s...
}

JSON

JSON是一种发送和接受格式化信息的标准,其并不是唯一的标准,xml,ASN.1和google的Protocol Buffer都是相似的标准,各自有使用的场景。但因为JSON简单,可读性强,并且支持广泛,所以用的最多。

package main

import (
	"encoding/json"
	"fmt"
)

type Movie struct {
	Title  string
	Year   int  `json:"released"` // field tags
	Color  bool `json:"color,omitempty"`
	Actors []string
}

var movies = []Movie{
	{
		Title: "Casablanca",
		Year:  1942,
		Color: false,
		Actors: []string{
			"Humphrey Bogart",
			"Ingrid Bergman",
		},
	},
	{
		Title: "Cool Hand Luke",
		Year:  1967,
		Color: true,
		Actors: []string{
			"Paul Newman",
		},
	},
	{
		Title: "Bullit",
		Year:  1968,
		Color: true,
		Actors: []string{
			"Steve McQueen",
			"Jacqueline Bisset",
		},
	},
}

func main() {
	data, err := json.MarshalIndent(movies, "", "    ")
	if err != nil {
		fmt.Printf("JSON marshaling failed: %s\n", err)
	}
	fmt.Printf("%s\n", data)

	// var antidata []struct{
	// 	Title string
	// 	Actors []string
	// }
	// var titles []string{Title string}
	var years []struct {
		Released int `json:"released"` // JSON字符串中的key为小写,所以定义可导出成员名,且还要使用field tag
	}
	if err := json.Unmarshal(data, &years); err != nil {
		fmt.Printf("%v\n", err)
	}
	fmt.Println(years)
}

成员标签(field tag)定义可以是任意字符串,但按照习惯,是由一串空格分开的key: "value"对。tag的值使用双引号括起来,所以标签都是原生的字符串字面量。tag的键 json 控制着encoding/json包的行为。encoding/...等包也遵循这样的规则。tag的值的第一部分指定了Go结构体成员对应JSON中字段的名字。成员标签通常这样使用,比如total_count对应Go里面的TotalCountColor的标签还有一个额外的选项omitempty,表示如果成员的值是零值或为空,则不输出这个成员到JSON中。

marshal的逆操作将JSON字符串解码为go数据结构,这个过程为unmarshal,由json.Unmarshal实现。通过合理定义Go的数据结构,可以选择将哪部分json数据解码到结构体对象中,哪些数据可以丢弃。

很多web服务都提供JSON接口,通过发送HTTP请求来获取想要得到的JSON信息。