Go 语言基础|青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天,初学Go,最大的感触就是语言真的是相通的,很多概念规则都可以类比我学过的C++和python,学得还是很开心的:D
map
map——哈希表,是一个由无序的key/value对构成的集合,类似于python的字典。map种不能有相同的key,因此key的类型K必须支持==运算。
创建map:
- 内置的make函数,和new很像,不过返回的不是指针,而是对应的类型(slice,map,channel)
ages := make(map[string]int)
ages["小红"] = 12
fmt.Println(ages) //map[小红:12]
- 直接利用map创建,同时利用类似于c++里的初始化列表初始化。
ages := map[string]int{"嬷嬷": 12}
ages["嬷嬷"] = 12 //map[嬷嬷:12]
fmt.Println(ages)
一些值得注意的点:
- 向一个nil值的map存入元素将导致一个panic异常:
var ages map[string]int
ages["嬷嬷"] = 12 //panic: assignment to entry in nil map
- 不能对map的元素进行取址操作:随着元素的增长,map可能会重新分配内存空间,那之前的取址值就无效了。
bad := &ages["小红"] //invalid operation: cannot take address of ages["小红"]
- 当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"}}
需要注意的点:
- 在编码时,默认使用Go语言结构体的成员名字作为JSON的对象。只有导出的结构体成员才会被编码,所以结构体里的成员名称要用大写字母开头。
- 如果我们要修改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语言圣经(中文版)