您现在的位置是:首页 >其他 >go破冰之旅·9·数组与切片(一)网站首页其他
go破冰之旅·9·数组与切片(一)
简介go破冰之旅·9·数组与切片(一)
一次5-10分钟即可搞定,实用+效率!
上文中,我们重点看了下函数的常用实践及各种玩法:函数相关
本文开始分为几小节我们来看看go中的数组和切片如何play,因篇幅和效率控制,本文重点看看数组。
目录
数组
数组是一批同数据类型的数据集合,是一个数据列表,它的特点如下:
1,就是存储的所有数据的数据类型都相同,数据类型既可以是内置的类型、也可以是自定义类型;
2,一经创建长度固定;
3,可以通过索引(0、1、2......第一个元素从0开始)来找到对应位置的元素。
下面我们来定义和使用数组:
// 定义一个整型数组,整型数组的意思就是该数组存放的是整型的数据
// 先声明,一会用
var arr0 [2]int
// len函数可以计算数组、切片、map等结构的长度。
fmt.Printf("len(arr0)= %v
", len(arr0)) // 长度肯定是0
// 给arr0数组增加元素:索引为0的位置元素是1,索引为1的位置元素是2
arr0 = [2]int{1, 2} // 如果设置的元素数量超过2个,则提示Index out of bounds: 2 ,编译都不会通过哦!
// 看看其中的元素和长度
fmt.Printf("len(arr0)=%d, arr0: %v
", len(arr0), arr0)
// 定义一个长度为3的字符串数组并赋值
var arr1 = [3]string{"A", "B", "C"}
fmt.Printf("len(arr1)=%d, arr1: %v
", len(arr1), arr1)
// 如果我不想只声明想直接创建好呢?先创建,一会用
arr2 := [3]string{}
arr2[0], arr2[1], arr2[2] = "D", "E", "F"
fmt.Printf("len(arr2)=%d, arr2: %v", len(arr2), arr2)
speed running:
len(arr0)= 2
len(arr0)=2, arr0: [1 2]
len(arr1)=3, arr1: [A B C]
len(arr2)=3, arr2: [D E F]
数组的变更(数组内容、指针等结合)
为避免多余的汉字干扰,这里将相关的解释和分析过程和代码结合起来,以注释的方式直接镶嵌进去,看起来会更清晰和轻快(每个字母都是作者手打,感谢支持):
// 如果不想赋所有值,先设置其中一部分呢?定义一个长度为3的字符串数组并赋0号位置的值
var arr3 = [3]string{"A"}
fmt.Printf("len(arr3)=%d, arr3: %v
", len(arr3), arr3)
// 设置索引为1的位置的元素
arr3[1] = "B"
fmt.Printf("len(arr3)=%d, arr3: %v
", len(arr3), arr3)
//arr3[3] = "D" // 超出数组边界设置,编译不会通过:Invalid array index 3 (out of bounds for 3-element array)
// 现在有一个长度为3的字符串数组arr4
var arr4 = [3]string{"A", "B", "C"}
// 我们直接赋给arr3,arr3的全部数据变为arr4的数据
arr3 = arr4 // 假设arr4长度设置为2: var arr4 = [3]string{"A"} 则会提示Cannot use 'arr4' (type [2]string) as type [3]string 编译不能通过
fmt.Printf("len(arr3)=%d, arr3: %v
", len(arr3), arr3)
// 现在有一个arr5,它指向着arr3的内存地址
arr5 := &arr3
// 先看看arr5是什么样、它俩的内存地址以及判断是否相等
fmt.Printf("len(arr5)=%d, arr5: %v, %p,%p, arr3==arr5: %v
", len(arr5), arr5, &arr3, arr5, arr3 == *arr5)
// 结果毫无悬念,数据相同,并且arr5保存的地址和arr3指向的地址完全一致,这里要重点注意说辞哦,&arr5和&arr3并不相同。
// 关于arr3 == *arr5,两者数据和数据类型(长度)完全相同(都引用的是同一快内存的数据),因此==判断为true
// 此种情况下,我们尝试修改arr5的2号元素的值为new试试
arr5[2] = "new"
fmt.Printf("len(arr5)=%d, arr5: %v
", len(*arr5), *arr5) // 注意,这里直接打印arr5也是能直观看到结果的
fmt.Printf("len(arr3)=%d, arr3: %v
", len(arr3), arr3) // len(arr3)=3, arr3: [A B new] 两者的索引为2位置的元素均被修改
相信看完上述举例和对应分析,你几乎都知道结果啦,一块展示出来:
len(arr3)=3, arr3: [A ]
len(arr3)=3, arr3: [A B ]
len(arr3)=3, arr3: [A B C]
len(arr5)=3, arr5: &[A B C], 0xc000076480,0xc000076480, arr3==arr5: true
len(arr5)=3, arr5: [A B new]
len(arr3)=3, arr3: [A B new]
数组指针 and 指针数组
关于数组指针、指针数组这两个概念,许多童鞋会被迷惑,实际就是字面意思并不复杂。
数组指针:你有一个数组,数组指针就是这个数组的指针;
指针数组:你有一个数组,数组内存储的元素都是指针类型的数据。
下面我们同样以典型的案例来予以说明:
arr0 := [2]int{1, 2}
// &arr0就是数组的指针,即数组指针,得到的结果就是一个指针地址
fmt.Printf("%p
", &arr0)
var a, b = 1, 2
// arr1存储的是两个int类型变量的地址
arr1 := []*int{&a, &b}
fmt.Printf("%v
", arr1) // 其每个元素就是指针地址,并不是真正的数据
// 那像arr1这种如何看到真实数据呢?
// 只看其中某个元素,如索引为0的元素时
fmt.Printf("%v
", *arr1[0])
// 得到arr1的所有数据时
for i, data := range arr1 {
fmt.Printf("index=%v, data=%v, addr=%v
", i, *data, data)
}
speed running:
0xc0000180b0
[0xc000018098 0xc0000180e0]
1
index=0, data=1, addr=0xc000018098
index=1, data=2, addr=0xc0000180e0
到这里,你应该豁然开朗了哦。
下文我们继续看看数据的其它特征,以及切片的玩法。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。