Golang 数组 Link to heading
声明数组 Link to heading
Go 语言提供了数组类型的数据结构。
数组是具有相同唯一类型的一组已编号且长度固定
的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:
var name [长度] 类型
声明名称为names
一个长度为 5,元素类型为字符串的:
var names [5]string
初始化数组 Link to heading
标准数组变量初始化:
var names = [5]string{"张学友", "刘德华", "黎明", "郭富城", "成龙"}
短变量初始化数组:
names2 := [5]string{"张学友", "刘德华", "黎明", "郭富城", "成龙"}
编译器推断长度:
names3 := []string{"张学友", "刘德华", "黎明", "郭富城", "成龙"}
完整代码:
package main
import "fmt"
func sum(arr [5]int) (sum int) {
sum = 0
for i, n := range arr {
fmt.Println(i, n)
sum += n
}
return
}
func main() {
var names = [5]string{"张学友", "刘德华", "黎明", "郭富城", "成龙"}
names1 := [5]string{"张学友", "刘德华", "黎明", "郭富城", "成龙"}
// 由编译器推断数组长度
names2 := [...]string{"张学友", "刘德华", "黎明", "郭富城", "成龙"}
names3 := [...]string{}
// 下面这行赋值编译报错
// names3[0] = "李修贤"
fmt.Printf("names: %T, %v\n", names, names)
fmt.Printf("names1: %T, %v\n", names1, names1)
fmt.Printf("names2: %T, %v\n", names2, names2)
fmt.Printf("names2: %T, %v\n", names3, names3)
}
go run go_slice_map.go
names: [5]string, [张学友 刘德华 黎明 郭富城 成龙]
names1: [5]string, [张学友 刘德华 黎明 郭富城 成龙]
names2: [5]string, [张学友 刘德华 黎明 郭富城 成龙]
names2: [0]string, []
由上可知 Golang 中数组的完整类型为元素长度及元素类型所组成。
同时在 Golang 中数组长度一旦被程序员指定,或由编译器推断则不可修改。为此 Golang 提供了Slice
切片来方便程序员操作数组,切片的底层是由数组所实现。
Golang 切片 Link to heading
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
// go_slice.go
package main
import "fmt"
func sum(nums []int) (sum int) {
sum = 0
for _, num := range nums {
sum += num
}
return
}
func printSlice(s []int) {
fmt.Printf("Type: %T, Value: %v, len: %d, cap: %d\n",
s, s, len(s), cap(s)*2,
)
}
func main() {
// 初始化一个切片
as := []int{1, 2, 3, 4}
fmt.Printf("%p\n", &as)
// 使用append函数对切片进行追加
as = append(as, 5)
fmt.Printf("%p\n", &as)
// 使用make函数初始切片
// 每个方法接受三个参数(类型,长度,容量)
// 其中容量参数可以省略,但长度及容量参数同时存在,长度值需小于等于容量值
// 容量为切片底层数组的长度
bs := make([]int, 4, 5)
cs := []int{6, 7, 8, 9, 10}
bs[0] = 1
bs[1] = 2
bs[2] = 3
bs[3] = 4
bs = append(bs, 5)
bs = append(bs, cs...)
printSlice(as)
printSlice(bs)
printSlice(cs)
ds := make([]int, len(bs), cap(bs)*2)
// 使用copy函数对切片进行复制
copy(ds, bs)
printSlice(ds)
fmt.Printf("Sum as: %d\n", as)
fmt.Printf("Sum bs: %d\n", bs)
fmt.Printf("Sum cs: %d\n", cs)
fmt.Printf("Sum ds: %d\n", ds)
// 切片截取
ds2 := ds[:3]
printSlice(ds2)
ds3 := ds[3:]
printSlice(ds3)
ds4 := ds[3:7]
printSlice(ds4)
ds5 := ds[:]
printSlice(ds5)
}
$ go run go_slice.go
0xc0000a0018
0xc0000a0018
Type: []int, Value: [1 2 3 4 5], len: 5, cap: 16
Type: []int, Value: [1 2 3 4 5 6 7 8 9 10], len: 10, cap: 20
Type: []int, Value: [6 7 8 9 10], len: 5, cap: 10
Type: []int, Value: [1 2 3 4 5 6 7 8 9 10], len: 10, cap: 40
Sum as: [1 2 3 4 5]
Sum bs: [1 2 3 4 5 6 7 8 9 10]
Sum cs: [6 7 8 9 10]
Sum ds: [1 2 3 4 5 6 7 8 9 10]
Type: []int, Value: [1 2 3], len: 3, cap: 40
Type: []int, Value: [4 5 6 7 8 9 10], len: 7, cap: 34
Type: []int, Value: [4 5 6 7], len: 4, cap: 34
Type: []int, Value: [1 2 3 4 5 6 7 8 9 10], len: 10, cap: 40
Golang Map(集合) Link to heading
Map 是一种无序的键值对的集合。
Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,遍历 Map 时返回的键值对的顺序是不确定的。
在获取 Map 的值时,如果键不存在,返回该类型的零值,例如 int 类型的零值是 0,string 类型的零值是 “"。
Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。
package main
import "fmt"
// 遍历指定类型的键值对
func PrintfMap(m map[string]string) {
for k, v := range m {
fmt.Printf("Key: %v, Value: %v\n", k, v)
}
}
func main() {
// 使用make内置函数声明map
var liming = make(map[string]string)
liming["name"] = "李明"
liming["age"] = "18"
liming["addrs"] = "北京"
// 使用短变量声明并初始化map
lilei := map[string]string{
"name": "李雷",
"age": "19",
"addrs": "广州",
}
// 下面这行赋值编译错误,键值类型需和声明是保持一致
// lilei["weight"] = 19
PrintfMap(lilei)
// 获取map键值长度
fmt.Printf("李明 len:%d\n", len(liming))
PrintfMap(liming)
fmt.Printf("李明 len:%d\n", len(liming))
fmt.Println("========================================")
// 修改map键值元素
liming["addrs"] = "上海"
PrintfMap(liming)
fmt.Printf("李明 len:%d\n", len(liming))
fmt.Println("========================================")
// 删除键
delete(liming, "addrs")
PrintfMap(liming)
fmt.Printf("李明 len:%d\n", len(liming))
}
Key: name, Value: 李雷
Key: age, Value: 19
Key: addrs, Value: 广州
李明 len:3
Key: name, Value: 李明
Key: age, Value: 18
Key: addrs, Value: 北京
李明 len:3
========================================
Key: name, Value: 李明
Key: age, Value: 18
Key: addrs, Value: 上海
李明 len:3
========================================
Key: name, Value: 李明
Key: age, Value: 18
李明 len:2