Go 之旅三: 复杂类型

本文是学习 A Tour of Go (中文参考 Go 之旅中文 ) 整理的笔记,介绍Go 语言的指针,结构体,数组,切片,映射和闭包的基本概念和使用。

1. 指针

$GOPATH/src/go_note/gotour/advancetype/pointer/pointer.go 源码如下:

Go 具有指针。 指针保存了变量的内存地址。类型 *T 是指向 T 类型值的指针,其零值为 nil 。

& 操作符会生成一个指向其操作数的指针。

* 操作符表示指针指向的底层值。

2. 结构体

$GOPATH/src/go_note/gotour/advancetype/struct/struct.go 源码如下:

一个结构体( struct )就是一个字段的集合,结构体字段使用点号来访问。

2.1 结构体指针

结构体字段可以通过结构体指针来访问。

如果我们有一个指向结构体的指针 pt ,那么可以通过 (*pt).X 来访问其字段 X,也可以使用隐式间接引用,直接写 pt.X

2.2 结构体语法

结构体文法通过直接列出字段的值来新分配一个结构体。

使用 Name: 语法可以仅列出部分字段。(字段名的顺序无关。)

特殊的前缀 & 返回一个指向结构体的指针。

3. 数组

$GOPATH/src/go_note/gotour/advancetype/array/array.go 源码如下:

类型 [n]T 表示拥有 nT 类型的值的数组。

表达式

数组的长度是其类型的一部分,因此数组不能改变大小

4. 切片

$GOPATH/src/go_note/gotour/advancetype/slice/slice.go 源码如下:

每个数组的大小都是固定的,而切片则提供动态数组,类型 []T 表示一个元素类型为 T 的切片。切片类似不限定长度的数组。

4.1 切片是数组的引用

切片并不存储任何数据,它只是描述了底层数组中的一段。更改切片的元素会修改其底层数组中对应的元素,并且与它共享底层数组的切片都会观测到这些修改。

如下创建一个切片时,会先创建数组,然后构建一个引用了它的切片

4.2 切片的默认行为

在进行切片时,切片有默认上下界。切片下界的默认值为 0 ,上界则是该切片的长度。

对于数组

来说,以下切片是等价的:

4.3 切片的长度与容量

切片拥有 长度容量

  • 长度就是它所包含的元素个数。
  • 容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。

切片 s 的长度和容量可通过表达式 len(s)cap(s) 来获取。

切片的零值是 nil, nil 切片的长度和容量为 0 且没有底层数组。

4.4 make 创建切片

切片可以用内建函数 make 来创建,这也是你创建动态数组的方式。make 函数会分配一个元素为零值的数组并返回一个引用了它的切片:

要指定它的容量,需向 make 传入第三个参数:

4.5 切片的切片

切片可包含任何类型,甚至包括其它的切片

4.6 append 向切片追加元素

为切片追加新的元素是种常用的操作,为此 Go 提供了内建的 append 函数

append 的第一个参数 s 是一个元素类型为 T 的切片, 其余类型为 T 的值将会追加到该切片的末尾。append 的结果是一个包含原切片所有元素加上新添加元素的切片。当 s 的底层数组太小,不足以容纳所有给定的值时,它就会分配一个更大的数组。 返回的切片会指向这个新分配的数组。

5. range

$GOPATH/src/go_note/gotour/advancetype/range/range.go 源码如下:

for 循环的 range 形式可遍历切片或映射。

当使用 for 循环遍历切片时,每次迭代都会返回两个值。 第一个值为当前元素的下标,第二个值为该下标所对应元素的一份副本。

可以将下标或值赋予 _ 来忽略它, 若你只需要索引,去掉 , value 的部分即可。

6. 映射

$GOPATH/src/go_note/gotour/advancetype/map/map.go 源码如下:

映射将键映射到值, 映射的零值为 nil, nil 映射既没有键,也不能添加键。make 函数会返回给定类型的映射,并将其初始化备用。

6.1 修改映射

在映射 m 中插入或修改元素:

获取元素:

删除元素:

通过双赋值检测某个键是否存在:

keym 中, oktrue ;否则, okfalse

key 不在映射中,那么 elem 是该映射元素类型的零值。同样的,当从映射中读取某个不存在的键时,结果是映射的元素类型的零值。

7. 闭包

$GOPATH/src/go_note/gotour/advancetype/closure/closure.go 源码如下:

函数也是值,它们可以像其它值一样传递,函数值可以用作函数的参数或返回值。

Go 函数可以是一个闭包。闭包是一个函数值,它引用了其函数体之外的变量。该函数可以访问并赋值其引用的变量的值,也即该函数被“绑定”在了这些变量上。

参考

发表评论