- 前言
- Go 与操作系统
- Go 内部机制
- Go 基本数据类型
- 4 组合类型的使用
- 5 数据结构
- 6 Go package 中不为人知的知识
- 7 反射和接口
- 8 Go UNIX 系统编程
- 08.1 关于 UNIX 进程
- 08.2 flag 包
- 8.2 flag 包
- 08.3 io.Reader 和 io.Writer 接口
- 08.4 bufio 包
- 08.5 读取文本文件
- 08.6 从文件中读取所需的数据量
- 08.7 为什么我们使用二进制格式
- 08.8 读取 CSV 文件
- 08.9 写入文件
- 08.10 从磁盘加载和保存数据
- 08.11 再看strings包
- 08.12 关于bytes包
- 08.13 文件权限
- 08.14 处理 Unix 信号
- 08.15 Unix 管道编程
- 08.16 遍历目录树
- 08.17 使用 ePBF
- 08.18 关于 syscall.PtraceRegs
- 08.19 跟踪系统调用
- 08.20 User ID 和 group ID
- 08.21 其他资源
- 08.22 练习
- 08.23 总结
- 9 并发 Goroutines、Channel 和 Pipeline
- 10 Go 并发-进阶讨论
- 11 代码测试、优化及分析
- 12 Go 网络编程基础
- 13 网络编程 - 构建服务器与客户端
03.3.1 切片基本操作
使用下面的代码可创建一个切片字面量:
aSliceLiteral := []int{1, 2, 3, 4, 5}
与定义数组相比,切片字面量只是没有指定元素数量。如果你在[]中填入数字,你将得到的是数组。
也可以使用 make()
创建一个空切片,并指定切片的长度和容量。容量这个参数可以省略,在这种情况下容量等于长度。
下面定义一个长度和容量均为20的空切片,并且在其需要的时候会自动扩容:
integer := make([]int, 20)
Go自动将空切片的元素初始化为对应元素的零值,意味着切片初始化时的值是由切片类型决定的。
使用下面的代码遍历切片中的元素:
for i :=0; i < len(integer); i++ {
fmt.Println(i)
}
切片变量的零值是 nil
, 下面代码可将已有的切片置为空:
aSliceLiteral = nil
可以使用 append()
函数追加元素到切片,此操作将触发切片自动扩容。
integer = append(integer, -5900)
integer[0]
代表切片integer的第一个元素,integer[len(integer)-1]
代表最后一个元素。
同时,使用[:]
操作可以获取连续多个元素,下面的代码表示获取第2、3个元素:
integer[1:3]
[:]
操作也可以帮助你从现有的切片或数组中创建新的切片或数组:
s2 := integer[1:3]
这种操作叫做re-slicing,在某种情况下可能会导致bug:
package main
import "fmt"
func main() {
s1 := make([]int, 5)
reSlice := s1[1:3]
fmt.Println(s1)
fmt.Println(reSlice)
reSlice[0] = -100
reSlice[1] = 123456
fmt.Println(s1)
fmt.Println(reSlice)
}
我们使用[:]
操作获取第2、3个元素。
假设有一个数组a1,你可以执行 s1 := a1[:]
来创建一个以a1为引用的切片
将上述代码保存为 reslice.go
并执行,将得到以下输出;
$ go run reslice.go
[0 0 0 0 0]
[0 0]
[0 -100 123456 0 0 ]
[-100 123456]
可以看到切片s1的输出是 [0 -100 123456 0 0 ]
,但是我们并没有直接改变s1。这说明通过re-slicing操作得到的切片,与原切片指向同一片内存地址!
re-slicing操作的第二个问题是,尽管你可能是想通过使用re-slicing从原切片中得到较小的一个切片,但是原切片的底层数组仍然会跟随着re-slicing得到的小切片,这对于小切片来说并不是什么严重问题,但是在这种情况下就可能导致bug:你将大文件的内容读到切片中,但是你只是想使用其中一小部分。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论