本文是在 GO 环境下测试记录系列之一,GO 基本环境部署步骤将略过,直接上代码。
下面是常用命令:【初始化 + 运行 + 编译】
// {GOPATH} 环境变量值, example 项目文件夹名称
{GOPATH}\src\example>
// 运行代码 // xxx.go 为文件全名
go run xxx.go
// 初始化 // 重复初始化提示:go: E:\Project\Go_WorkSpace\src\example\go.mod already exists
go mod init // 初始化成功时没有输出
go mod tidy // 添加缺少的或删除不需要的模块
// 编译,将源代码编译成可执行程序(.exe) // 可选项:-o xxx.exe 自定义应用程序名
go build [-o xxx.exe]
slice 并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案。它有如下特点:
切片的定义:var 变量名 []类型,比如:var str []string、var arr []int。
语法:
var slice []type = make([]type, len) // 全局变量
slice := make([]type, len) // 局部变量
slice := make([]type, len, cap)
测试一下:
package main
import (
"fmt"
)
func main() {
s1 := make([]int, 2) // 等同于:make([]int, 2, 2)
fmt.Printf("slice s1 : %v\n", s1)
fmt.Printf("slice s1-len : %v\n", len(s1))
fmt.Printf("slice s1-cap : %v\n", cap(s1))
s2 := make([]int, 2, 4)
fmt.Printf("slice s2 : %v\n", s2)
s3 := make([]int, 3, 4)
fmt.Printf("slice s3 : %v\n", s3)
fmt.Printf("slice s3-len : %v\n", len(s3))
fmt.Printf("slice s3-cap : %v\n", cap(s3))
}
测试目的:通过 append 方法添加元素,超出 slice 的 cap 值。
package main
import (
"fmt"
)
func main() {
data := [...]int{0, 1, 2, 3, 4, 10: 0}
s := data[:2:3]
fmt.Println("data[:2:3]")
fmt.Println(len(s))
fmt.Println(cap(s))
fmt.Println("append(s, 100, 200)")
s = append(s, 100, 200) // 一次 append 两个值,超出 s.cap 限制
fmt.Println(len(s))
fmt.Println(cap(s))
fmt.Println("append(s, 1000, 2000, 3000)")
s = append(s, 1000, 2000, 3000) // 一次 append 两个值,超出 s.cap 限制
fmt.Println(len(s))
fmt.Println(cap(s))
fmt.Println(&s[0], s) // 重新分配底层数组,与原数组无关
fmt.Println(&data[0], data) // 比对底层数组起始指针
}
详解:
注意:切片数组的容量增加,是在原容量的基础上乘与 2,无论原容量是多少。
通过array[start : end : cap_value]
开始和结束的整数值来指定截取范围,cap_value 标识容量。
package main
import (
"fmt"
)
func main() {
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
ss := data[2:4] // 截取 2~4 位,且不包含 4
fmt.Println(ss)
fmt.Printf("slice len(ss) : %v\n", len(ss))
fmt.Printf("slice cap(ss) : %v\n", cap(ss))
s := data[2:4:7] // 截取 2~4 位,且不包含 4。容量截取到 7 位,且不包含 7
fmt.Println(s)
fmt.Printf("slice len(s) : %v\n", len(s))
fmt.Printf("slice cap(s) : %v\n", cap(s))
s[0] += 100
p := &s[0] // 获取切片 s 中首个数据存储的地址
*p += 10 // *int 获取底层数组元素的指针
s[1] += 200
fmt.Println(s)
fmt.Println(data)
}
如下代码,声明数组并定义其切片数组,然后分别对两者的一个数值位赋值:
package main
import (
"fmt"
)
func main() {
d := [5]struct {
x int
}{}
s := d[:]
d[1].x = 10
s[2].x = 20
fmt.Println(d)
fmt.Println(s)
fmt.Printf("%p, %p\n", &d, &d[0])
fmt.Printf("%p, %p\n", &s, &s[0])
}
由上结果可知,数组和切片的实际值指的是同一个段内存中的数据,切片只是增加了对数组的一个引用。
函数 copy 在两个 slice 间复制数据,复制长度以 len 小的为准(换句话说就是,将重叠位的数据进行复制)。两个 slice 可指向同一底层数组,允许元素区间重叠。
应及时将所需数据 copy 到较小的 slice,以便释放超大号底层数组内存。
package main
import (
"fmt"
)
func main() {
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("array data : ", data)
s1 := data[8:]
s2 := data[:5]
fmt.Printf("slice s1 : %v\n", s1)
fmt.Printf("slice s2 : %v\n", s2)
copy(s2, s1) // 短 -> 长
fmt.Printf("copied slice s1 : %v\n", s1)
fmt.Printf("copied slice s2 : %v\n", s2)
fmt.Println("array data : ", data)
fmt.Println("------------------------------------------")
data2 := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("array data2 : ", data2)
s3 := data2[8:]
s4 := data2[:5]
fmt.Printf("slice s3 : %v\n", s3)
fmt.Printf("slice s4 : %v\n", s4)
copy(s3, s4) // 长 -> 短
fmt.Printf("copied slice s3 : %v\n", s3)
fmt.Printf("copied slice s4 : %v\n", s4)
fmt.Println("array data2 : ", data2)
}
package main
import (
"fmt"
)
func main() {
data := [...]int{0, 1, 2}
slice := data[:]
for index, value := range slice {
fmt.Printf("index : %v , value : %v\n", index, value)
}
}
string 底层就是一个 byte 的数组,因此,也可以进行切片操作。
组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号(’)包裹起来。
Go 语言中字符分两种:
因此 rune 类型可以是由一个或多个 byte 类型组成。
如下示例代码,将“世界”修改为“够浪”,其对应的 UTF-8 字符也随之改变。
package main
import (
"fmt"
)
func main() {
str := "你好,世界!GO!"
fmt.Println(str)
s := []rune(str)
for index, value := range s {
fmt.Printf("index: %v , value : %v\n", index, value)
}
s[3] = '够'
s[4] = '浪'
s = s[:]
str = string(s)
fmt.Println(str)
for index, value := range s {
fmt.Printf("index: %v , value : %v\n", index, value)
}
}
参考:http://www.topgoer.com/http://www.topgoer.com/go%E5%9F%BA%E7%A1%80/%E5%88%87%E7%89%87Slice.html