Go 语言容器类型

本文介绍了Go语言中数组、切片和map的基本概念、声明方式,重点讲解了数组的固定长度、切片的动态扩展、以及map的无序键值对存储。还涉及了切片的长度、容量、复制和相关内建函数,以及map的遍历和操作技巧。
摘要由CSDN通过智能技术生成

数组

Go语⾔当中,可以将⼀组类型相同的数据存放在⼀个数组当中,数组中元素的类型可以是Go语⾔原⽣
类型,也可以是⾃定义类型(struct)。声明⽅式可以参考变量:

var variable_name [SIZE] variable_type
var sa [10] int64 //定义⼀个10个int64类型的数组
var ss [3] string = [3]string{"lily","lucy","lilei"}//定义3个⻓度的字符数组
package main

import "fmt"

func main()  {
	// 定义5个元素的整型数组
	var five [5]int = [5]int{1,2,3,4,5}
	// 定义3个元素的字符串数组
	var three [3]string=[3]string{"zhangsan","lisi","wangwu"}
	fmt.Println(five)
	fmt.Println(three)
}

结果
[1 2 3 4 5]
[zhangsan lisi wangwu]

注意:数组是固定⻓度的,不可以越界!

在Go语⾔当中,同样可以定义⼆维数组

package main
import (
	"fmt"
)
func main() {
	//Go语⾔当中的⼆维数组,可以理解为3⾏4列
	a2 := [3][4]int{
		{0, 1, 2, 3}, /* 第⼀⾏索引为 0 */
		{4, 5, 6, 7}, /* 第⼆⾏索引为 1 */
		{8, 9, 10, 11}, /* 第三⾏索引为 2 */
	}
	//注意上述数组初始化的逗号
	fmt.Println(a2)
	//如何遍历该数组?可以写2层for循环搞定
	for i := 0; i < 3; i++ {
		for j := 0; j < 4; j++ {
			fmt.Printf("i = %d, j = %d, val = %d\n", i, j, a2[i][j])
		}
	}
}

结果
[[0 1 2 3] [4 5 6 7] [8 9 10 11]]
i = 0, j = 0, val = 0
i = 0, j = 1, val = 1
i = 0, j = 2, val = 2
i = 0, j = 3, val = 3
i = 1, j = 0, val = 4
i = 1, j = 1, val = 5
i = 1, j = 2, val = 6
i = 1, j = 3, val = 7
i = 2, j = 0, val = 8
i = 2, j = 1, val = 9
i = 2, j = 2, val = 10
i = 2, j = 3, val = 11

切⽚

由于数组是固定⼤⼩的,这在使⽤上缺少⼀定便利,因此Go语⾔⼜提供了切⽚类型,乍⼀看切⽚与数组
没有区别,只不过它的⼤⼩是可以扩充的,也就是说可以把切⽚理解成动态数组,⾄于为什么叫切⽚,
可以脑补⼀下⾯包⽚(⻓⾯包想象成⼀个数组,切⽚是从其某段切下来)。

切⽚中有2个概念:⻓度和容量

  • ⻓度 指被赋过值的最⼤下标+1
  • 容量 指切⽚能容纳的最多元素个数
    其实内部还有一个数据指针来指向这些数据的空间地址

切⽚可以⽤array|slice[start:end]的⽅式进⾏截取,得到新的切⽚,其中start和end代表下标位置,都
可以省略,start省略代表从头开始,end省略代表直到末尾。

package main
import (
	"fmt"
)
func main() {
	a1 := [5]int{1, 2, 3, 4, 5} // a1 是⼀个数组
	fmt.Println(a1)
	s1 := a1[2:4] //定义⼀个切⽚
	fmt.Println(s1)
	s1[1] = 100 //切⽚下标不能超过
	fmt.Println("after---切片修改会影响原数组")
	fmt.Println(a1)
	fmt.Println(s1)
}

结果
[1 2 3 4 5]
[3 4]
after---切片修改会影响原数组
[1 2 3 100 5]
[3 100]

通过上述例⼦,我们可以得出2个知识点:

  1. 切⽚start:end是前闭后开,也就是实际截取下标是start到end-1
  2. 切⽚是引⽤类型,对切⽚的修改会影响对应的数组

与切⽚相关的内建函数:

len(s)
  • 计算切⽚容量.
cap(s)
  • append 向切⽚追加元素
var s1 []T
append(s1,T)
  • make 可以创建切⽚
make([]T, length, capacity) //capacity 可以省略,默认与len⼀致
  • copy 复制切⽚
copy(s2,s1) //将s1内容拷⻉到s2,此时s1与s2是独⽴的,修改互不⼲预
package main

import "fmt"

func main() {
	var s1 []int //定义切⽚s1
	s1 = append(s1, 1) //追加,注意s1必须接收追加结果
	s1 = append(s1, 2)
	s1 = append(s1, 3, 4, 5) //可以⼀次追加多个
	printSlice(s1)
	s2 := make([]int, 3)
	printSlice(s2)
	s2 = append(s2, 4) //当超过容量的时候,容量会以len*2的⽅式⾃动扩⼤
	printSlice(s2)
	copy(s1,s2)
	printSlice(s1)
	s2[0]=1000
	printSlice(s2)
}

func printSlice(s []int) {
	fmt.Printf("len = %d, cap = %d, s = %v\n", len(s), cap(s), s)
}

结果
len = 5, cap = 6, s = [1 2 3 4 5]
len = 3, cap = 3, s = [0 0 0]
len = 4, cap = 6, s = [0 0 0 4]
len = 5, cap = 6, s = [0 0 0 4 5]
len = 4, cap = 6, s = [1000 0 0 4]

当切⽚容量不够时,追加不会报错,⽽会扩⼤容量,扩⼤容量默认采⽤len*2
的数据。根据多个例⼦编写,Go语⾔默认都会对变量进⾏初始化,这⼀点很友好!

map(键值对)

Go语⾔同样提供了map这样的容器,map可以存放⽆序的键值对,map是⼀种集合,但注意它是⽆序
的。map需要使⽤make来构造,否则它是⼀个nil-map,⽆法存放键值对。

var map_variable map[key_data_type]value_data_type
map_variable = make(map[key_data_type]value_data_type)
或
map_variable := make(map[key_data_type]value_data_type)
package main

import "fmt"

func main() {
	countryCapitalMap := make(map[string]string)
	// map插⼊key - value对,各个国家对应的⾸都
	countryCapitalMap["France"] = "Paris"
	countryCapitalMap["Italy"] = "Roma"
	countryCapitalMap["China"] = "BeiJing"
	countryCapitalMap["India "] = "New Delhi"
	fmt.Println(countryCapitalMap["China"])
	//当key不存在时,直接打印不太优雅,可以使⽤下⾯的⽅法
	val, ok := countryCapitalMap["Japan"]
	if ok {
		fmt.Println("Japan's capital is", val)
	} else {
		fmt.Println("Japan's capital not in map")
	}
}

结果
BeiJing
Japan's capital not in map

在取map的值时可以⽤⼀个变量接收,也可以增加⼀个指示变量,来判断key值是否真实存在。下⾯还
有⼀个问题,如何对map进⾏遍历呢?这需要⽤到range关键字,它可以让我们优雅的遍历Go语⾔各种
容器,当然包括map。具体⽤法可以看代码:

package main

import "fmt"

func main() {
	countryCapitalMap := make(map[string]string)
	// map插⼊key - value对,各个国家对应的⾸都
	countryCapitalMap["France"] = "Paris"
	countryCapitalMap["Italy"] = "Roma"
	countryCapitalMap["China"] = "BeiJing"
	countryCapitalMap["India "] = "New Delhi"
	//遍历map
	for k, v := range countryCapitalMap {
		fmt.Println(k, "'s capital is", v) //k,v分别是map的key和val
	}
	//遍历数组,如果不想获得
	a := []int{10, 20, 30, 40, 50}
	for k, v := range a {
		fmt.Printf("a[%d]=%d\n", k, v) //k代表数组下标,v代表该元素值
	}
}

结果
France 's capital is Paris
Italy 's capital is Roma
China 's capital is BeiJing
India  's capital is New Delhi
a[0]=10
a[1]=20
a[2]=30
a[3]=40
a[4]=50

如果不想获得k或v的值时,可以⽤_占位,这个语法在其他多变量赋值时同样适⽤。

_, v := range countryCapitalMap //只取v的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季布,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值