Go语言中的内建容器

数组(Array)

数组的定义

数组是一种线性数据结构,是一个存放相同类型数据的定长序列。数组中的元素在内存中是连续存储的,每个元素占用的内存大小相同,且每个元素都有一个唯一的索引,通过索引可以快速访问到对应的元素。

在 Go 语言中,数组的声明形式为:var 数组名 [数组长度]数据类型

其中数据类型也可以是数组,也就是数组类型的数组,这样就构成了多维数组。和变量的声明一样,数组在声明是会初始化变量类型的零值。

示例代码:

// 声明一个长度为 5 的整型数组
var arr1 [5]int

// 声明一个长度为 3 的整型数组,并且赋值为[1, 2, 3]
var arr2 [3]int{1, 2, 3}

// 使用 ... 表示由编译器根据值来自行计算数组长度
var arr3 [...]int{0, 2, 4, 6, 8}

// 声明一个 4 行 5 列的二维整型数组
var arr4 [4][5]int

数组的大小也是类型的一部分

Go 语言中判断两个数组是否相等会比较两个部分,一是数组的长度是否相等,二是数组中存放的值顺序和大小是否相等。比如, [5]int 和 [10]int 就是两个不同的类型。

示例代码:

var a [2]int
var b = [2]int{1, 2}
var c = [...]int{1, 2}

fmt.Println("a == b ? ", a == b)	//false
fmt.Println("b == c ?", b == c)		//true

数组是值类型

Go 语言中数组是值类型而不是引用类型,这意味着当把一个数组赋值给一个新变量时,该变量会得到原始数组的一个副本,对新变量进行修改不会影响到原始数组。

示例代码:

a := [5]int{1, 3, 5, 7, 9}
b := a
b[0] = 100

fmt.Println(a)	// 输出:1, 3, 5, 7, 9
fmt.Println(b)	// 输出:100, 3, 5, 7, 9

数组的遍历

在 Go 语言中可以通过 len() 函数获取数组长度,然后使用 for 循环进行遍历;此外,还提供了一种更简洁的方式,通过 range 关键字来遍历,range 会返回索引和该索引的值。

示例代码:

arr := [...]int{2, 4, 6, 8}

for i := 0; i < len(arr); i++ {
	fmt.Println(arr[i])
}

for i, v := range arr {
	fmt.Println(i, v)
}

切片(Slice)

Slice 的定义

Slice 是由数组创建的一种方便、灵活且功能强大的包装。Slice 本身没有数据,是对现有数组的引用。

Slice 在使用之前必须初始化,它没有零值。它的底层实现是一个指向数组的指针,在给它存入地址之前,它只能是 nil。

Slice 的声明方式与数组类似,写法上就像是一个没有长度的数组:var 切片名 []数据类型

数据类型也可以是 Slice,也就是 Slice 类型的 Slice,就构成了多维 Slice。

示例代码:

// 创建一个空的 Slice
var s1 []int

// 创建一个指向数组 [2, 4, 6, 8] 的 Slice
s2 := []int{2, 4, 6, 8}

// 通过内置函数 make() 创建一个长度 16 的 Slice
s3 := make([]int, 16)

// 创建一个长度 16,容量 32 的 Slice
s4 := make([]int, 16, 32)

// 从数组中创建 Slice, a[1:3] 表示从 a 中截取索引 1 到 4 的内容(左开右闭)
a := [...]int{1, 3, 5, 7, 9}
s5 := a[1:4]	// s5 = [3, 5, 7]

Slice 的常用操作

Slice 自己不能拥有数据,是对底层数组的视图,对 Slice 进行的操作都会反映到原数组中。当一个数组有多个 Slice 时,所有 Slice 的更改都会反映在数组当中。

Slice 的长度是 Slice 中元素的个数,可以用函数 len() 获取,Slice 的容量是底层数组从创建 Slice 的索引开始到最后的元素个数,可以用函数 cap() 获取。

Slice 的长度是动态的,可以使用内置函数 append() 追加元素到尾部,如果 Slice 的长度超过了容量,会自动引用一个更大的数组来存放这些元素。

示例代码:

// arr 的长度为 100
arr := [100]int{0, 1, 2}

// 截取索引 2 到 6 创建 Slice
s1 := arr[2:6]

fmt.Println(len(s1),cap(s1))	//len(s1) == 4, cap(s1) == 98

// 追加元素
s1 = append(s, 11, 12)

// 复制
s2 := make([]int, 8)
copy(s2, s1)
fmt.Println(s2)

//从中间删除某一元素,Go 语言中没有对应的删除函数,使用 append() 也可以达到效果
s1 = append(s1[:4], s1[5:]...)

// 遍历方式和数组一致
for i := 0; i < len(s1); i++ {
	fmt.Println(s1[i])
}

for i, v := range s1 {
	fmt.Println(i, v)
}

字典(Map)

Map 的定义

Map 是 Go 语言中一种键(key)与值(value)关联的内置类型,具有无序、key 不可重复等特点。能够通过 key 快速找到 value,也被称为字典。

Map 的声明形式为:var 字典名 map[键类型]值类型

Map 之间不能使用 == 号进行判断,== 只能用来检查 Map 是否为 nil。

Map 的底层是一个指针,和变量不同,并不是声明后就可使用。与 Slice 相似,需要使用 make() 函数进行初始化,在初始化之前为空,没有零值。

示例代码:

// 仅声明,此时 map 不可用
var m1 map[string]string
fmt.Println(m1 == nil)	// 输出:true 

// 使用 make() 函数初始化
m2 := make(map[string]string)
fmt.Println(m2 == nil)	// 输出:false

// 声明同时赋值
m3 := map[string]string{
	"name":   "aaa",
	"course": "bbb",
	"site":   "ccc",
}

// 使用map[key]=value的形式对map进行赋值
m2["name"] = "aaa"
m2["course"] = "bbb"

Map 的常用操作

  1. 获取 map 中指定 key 的元素,语法为:map[key]
m := map[string]string{
	"name":   "aaa",
	"course": "bbb",
	"site":   "ccc",
}

// 获取 map 中指定 key 的元素:map[key]
fmt.Println(m["name"])

// 当 map 中不存在这个 key 时,会返回空字符串
fmt.Println(m["abc"])

// 可以使用以下语法判断 key 是否存在
// 如果 key 存在,value 就是 key 所对应的元素,ok == true,否则 value 为零值,ok == false
value, ok := m["name"]
  1. 遍历 map 中的所有元素可以使用 for range 循环,与遍历数组和 Slice 用法一致。
m := map[string]string{
	"name":   "aaa",
	"course": "bbb",
	"site":   "ccc",
}

for k, v := range m3 {
	fmt.Println(k, v)
}
  1. 删除 map 中的元素,需要使用内置函数 delete(),该函数没有返回值。
m := map[string]string{
	"name":   "aaa",
	"course": "bbb",
	"site":   "ccc",
}

delete(m, "name")

使用 Map 的一些注意事项

Map 是一个哈希表,key 必须可以比较相等,除了 Slice、map、function 之外的内建类型都可以作为 key,Struct 类型不包含这三种类型的字段,也可以作为 key。

Map 是线程不安全的,在多线程环境下,必须采取特殊的措施来保证 Map 的线程安全(比如使用sync包下的锁机制)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值