[日常] Go语言圣经--结构体,JSON习题
Go语言圣经-结构体
1.结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体
2.通常一行对应一个结构体成员,成员的名字在前类型在后,不过如果相邻的成员类型如果相同的话可以被合并到一行
3.如果结构体成员名字是以大写字母开头的,那么该成员就是导出的;这是Go语言导出规则决定的。一个结构体可能同时包含导出和未导出的成员。
4.一个命名为S的结构体类型将不能再包含S类型的成员:因为一个聚合的值不能包含它自身,S类型的结构体可以包含*S指针类型的成员
我们使用一个二叉树来实现一个插入排序:
5.结构体类型的零值是每个成员都是零值。通常会将零值作为最合理的默认值
6.结构体字面值,第一种要求以结构体成员定义的顺序为每个结构体成员指定一个字面值
第二种写法,以成员名字和相应的值来初始化,可以包含部分或全部的成员,更常用
7.企图隐式使用未导出成员的行为是不允许的
8.如果考虑效率的话,较大的结构体通常会用指针的方式传入和返回,函数中
9.如果要在函数内部修改结构体成员的话,用指针传入是必须的;因为在Go语言中,所有的函数参数都是值拷贝传入的,函数参数将不再是函数调用时的原始变量。
10.结构体比较,如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的
11.可比较的结构体类型和其他可比较的类型一样,可以用于map的key类型。
12.结构体嵌入和匿名成员,让我们只声明一个成员对应的数据类型而不指名成员的名字;这类成员就叫匿名成员,得意于匿名嵌入的特性,我们可以直接访问叶子属性而不需要给出完整的路径:
13.结构体字面值并没有简短表示匿名成员的语法
14.Printf函数中%v参数包含的#副词,它表示用和Go语言类似的语法打印值。对于结构体类型来说,将包含每个成员的名字。
Go语言圣经-JSON
1.标准库中的encoding/json、encoding/xml、encoding/asn1等包提供支持
2.一个JSON数组可以用于编码Go语言的数组和slice
3.JSON的对象类型可以用于编码Go语言的map类型(key类型是字符串)和结构体
4.将一个Go语言中类似movies的结构体slice转为JSON的过程叫编组(marshaling)。编组通过调用json.Marshal函数完成,返还一个编码后的字节slice,包含很长的字符串
5.json.MarshalIndent函数将产生整齐缩进的输出,两个额外的字符串参数用于表示每一行输出的前缀和每一个层级的缩进
6.只有导出的结构体成员才会被编码,这也就是我们为什么选择用大写字母开头的成员名称
7.结构体的成员Tag可以是任意的字符串面值,但是通常是一系列用空格分隔的key:"value"键值对序列;因为值中含义双引号字符,因此成员Tag一般用原生字符串面值的形式书写
8.编码的逆操作是解码,对应将JSON数据解码为Go语言的数据结构,Go语言中一般叫unmarshaling,通过json.Unmarshal函数完成
9.用url.QueryEscape来对查询中的特殊字符进行转义操作。
10.使用了基于流式的解码器json.Decoder,它可以从一个输入流解码JSON数据,还有一个针对输出流的json.Encoder编码对象
练习 4.10: 修改issues程序,根据问题的时间进行分类,比如不到一个月的、不到一年的、超过一年。
练习 4.11: 编写一个工具,允许用户在命令行创建、读取、更新和关闭GitHub上的issue,当必要的时候自动打开用户默认的编辑器用于输入文本信息。
练习 4.12: 流行的web漫画服务xkcd也提供了JSON接口。例如,一个 https://xkcd.com/571/info.0.json 请求将返回一个很多人喜爱的571编号的详细描述。下载每个链接(只下载一次)然后创建一个离线索引。编写一个xkcd工具,使用这些离线索引,打印和命令行输入的检索词相匹配的漫画的URL。
练习 4.13: 使用开放电影数据库的JSON服务接口,允许你检索和下载 https://omdbapi.com/ 上电影的名字和对应的海报图像。编写一个poster工具,通过命令行输入的电影名字,下载对应的海报。
// Issues prints a table of GitHub issues matching the search terms. package main import ( "fmt" "github" "log" "os" "time" ) /* 练习 4.10: 修改issues程序,根据问题的时间进行分类,比如不到一个月的、不到一年的、超过一年。 */ func main() { result, err := github.SearchIssues(os.Args[1:]) if err != nil { log.Fatal(err) } fmt.Printf("%d issues:\n", result.TotalCount) //当前时间 now := time.Now().Unix() //前一个月 preMonth := now - 30*24*3600 //前一年 preYear := now - 365*24*3600 var notMonth []*github.Issue var notYear []*github.Issue var overYear []*github.Issue for _, item := range result.Items { createTime := item.CreatedAt.Unix() if createTime > preMonth { notMonth = append(notMonth, item) continue } if createTime < preMonth && createTime > preYear { notYear = append(notYear, item) continue } overYear = append(overYear, item) } fmt.Println("issues(不到一个月):") for _, item := range notMonth { fmt.Printf("#%-5d %9.9s %.55s 时间:%s\n", item.Number, item.User.Login, item.Title, item.CreatedAt) } fmt.Println("issues(不到一年):") for _, item := range notYear { fmt.Printf("#%-5d %9.9s %.55s 时间:%s\n", item.Number, item.User.Login, item.Title, item.CreatedAt) } fmt.Println("issues(超过一年):") for _, item := range overYear { fmt.Printf("#%-5d %9.9s %.55s 时间:%s\n", item.Number, item.User.Login, item.Title, item.CreatedAt) } }