Go 语言基础|青训营笔记

21 阅读4分钟

Go 语言基础|青训营笔记

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天,初学Go,最大的感触就是语言真的是相通的,很多概念规则都可以类比我学过的C++和python,学得还是很开心的:D

map

map——哈希表,是一个由无序的key/value对构成的集合,类似于python的字典。map种不能有相同的key,因此key的类型K必须支持==运算。

创建map:

  1. 内置的make函数,和new很像,不过返回的不是指针,而是对应的类型(slice,map,channel)
ages := make(map[string]int)
ages["小红"] = 12
fmt.Println(ages) //map[小红:12]
  1. 直接利用map创建,同时利用类似于c++里的初始化列表初始化。
ages := map[string]int{"嬷嬷": 12}
ages["嬷嬷"] = 12 //map[嬷嬷:12]
fmt.Println(ages)

一些值得注意的点:

  1. 向一个nil值的map存入元素将导致一个panic异常:
var ages map[string]int
ages["嬷嬷"] = 12 //panic: assignment to entry in nil map
  1. 不能对map的元素进行取址操作:随着元素的增长,map可能会重新分配内存空间,那之前的取址值就无效了。
bad := &ages["小红"] //invalid operation: cannot take address of ages["小红"]
  1. 当key不存在时,返回第一个值为对应value的零值,第二个值为false,代表key不存在
age, ok := age["unknow"]  // 0 false

结构体方法

刚学习完Go的函数,看到下面的函数写法,让我有点转不来:

type user struct {
	name     string
	password string
}

func (u *user) resetPassword(password string) {
	u.password = password
}

原来,这是结构体方法的写法,它和普通的函数声明一样,不过在函数名前面加了一个参数,表示把这个方法绑定到这个参数对应的类型上,实际是一种面向对象的编程思想,类似的,可以很方便的为简单的类型(如整形、字符串、slice、map、甚至函数等)定义附加的行为。对象可以通过.来访问该方法。

JSON

我们把下面的结构体转化为JSON:

type userInfo struct {
	Name  string
	Age   int `json:"age"`
	Hobby []string
}

可以通过调用json.Marshal函数完成转化,返回一个编码后的字节slice,用string()将其转化为字符串,或者直接用printf()的格式化方法,由下图可见,最后的输出没有空白缩进。

a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
	buf, err := json.Marshal(a)
	if err != nil {
		panic(err)
	}
	fmt.Println(buf)         // [123 34 78 97...] 返回的是byte数组
	fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
	fmt.Printf("%s\n", buf)  // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}

也可以用json.MarshalIndent函数,将产生整齐缩进的输出。该函数有两个额外的字符串参数用于表示每一行输出的前缀,和每一个层级的缩进:

buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
        panic(err)
}
fmt.Println(string(buf))

/*输出结果如下:
{
        "Name": "wang",
        "age": 18,
        "Hobby": [
                "Golang",
                "TypeScript"
        ]
}
*/

编码的逆操作是解码,对应将JSON数据解码为Go语言的数据结构,通过json.Unmarshal函数完成。

var b userInfo
err = json.Unmarshal(buf, &b) //第二个参数是指针
if err != nil {
        panic(err)
}
fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}

需要注意的点:

  1. 在编码时,默认使用Go语言结构体的成员名字作为JSON的对象。只有导出的结构体成员才会被编码,所以结构体里的成员名称要用大写字母开头。
  2. 如果我们要修改JSON对象的名字,可以利用结构体的成员tag,也就是上述代码中的json:"age"来重新给JSON对象命名

fmt.Scanf

在改第一个猜谜游戏的时候用到了这个函数用来替代bufio.NewReader. 函数声明如下:

func fmt.Scanf(format string, a ...any) (n int, err error)

//举个栗子
_, err := fmt.Scanf("%d\n", &guess)

Scanf 从标准输入按照format指定的格式,以空格分隔读取输入到相应的变量。返回两个参数,n是成功读入的项的数目,如果比输入的参数少的话,第二个参数err就会报告。 值得注意的是,format参数最后要有一个\n和输入末尾的换行符匹配,否则,会报unexpected newline的err。

参考

标题:Go语言圣经(中文版)

网址:books.studygolang.com/gopl-zh/