go的高级数据与结构类型
Posted traditional
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go的高级数据与结构类型相关的知识,希望对你有一定的参考价值。
1.go的数组与切片
package main import "fmt" /* 数组是go语言编程中最常用的结构之一。顾名思义,数组就是一系列同一类型数据的集合。 数组中包含的每一个元素成为数组元素(element),一个数组包含的元素的个数被称为数组长度 */ func main(){ var arr1 [5]int //声明一个数组arr1,里面可以存五个int类型的数据 fmt.Println(arr1) //[0 0 0 0 0],没有初始化,go语言也不会报错,会默认初始化为零值 //还可以修改 arr1[1] = 100 //修改数组会直接在数组本身上修改,但是不可以越界,不可以arr[7] = 100 fmt.Println(arr1) //[0 100 0 0 0] var arr2 = [5]int{1,2,3} //初始化只给三个值,那么剩余的会自动用零值填充 fmt.Println(arr2) //1 2 3 0 0] //如果我们不确定有多少个元素,或者我们不想数,该怎么办呢? var arr3 = [...]int{15,112,4,2} //使用...表示让编译器帮我们数有多少个元素,而且我们输入几个元素,就代表数组的长度是多少 fmt.Println(arr3) //[15 112 4 2] //我们在初始化数组的时候,还可以指定某几个元素的值 //比方说我初始化长度为10的数组,但指定索引为2的值是10,索引为8的元素是25,怎么做呢? var arr4 = [10]int{2:10,8:25} fmt.Println(arr4) //[0 0 10 0 0 0 0 0 25 0] //如果我这里没有指定数组长度,而是用...代替的话,那么arr4的长度就为9 //因为我们这里指定索引为8的元素是25,那么编译器就将数组的最大索引定位8,所以是9个元素 //如果我们初始化 var arr4 = [...]{100: 20}, 那么长度就是101 //因为我们既然指定了索引为100的值是20,那么数组至少有101个,而我们又是...,那么go编译器就直接默认生成长度为101的数组 }
package main import "fmt" /* 在go中,切片是长度可变,容量固定的相同元素的数列。 go切片本质上是一个数组,容量固定是因为数组的容量是固定的,切片的容量就是隐藏数组的长度,切片的长度可变是指在数组的长度范围内可变 怎么理解呢?切片可以看做指向数组的指针,切片具有长度和容量 长度:切片元素的个数 容量:切片底层数组的个数 切片的定义方式和数组类似,不同的是[]里面不需要任何东西 */ func main() { var slice1= []int{1, 2, 3, 4, 5, 6} //len表示切片的长度,cap表示切片的容量也就是底层数组的长度 //不过这里貌似没有底层数组,就把[6]int{1,2,3,4,5,6]看成底层数组就可以了 fmt.Println(len(slice1), cap(slice1)) // 6 6 ,此时切片的长度和容量都是6 //我们初始化一个数组 var arr= [...]int{1, 2, 3, 4, 5, 6} var slice2= arr[:] //此时的arr就是slice2的底层数组,可以把slice2看成是arr的view,通过切片来看底层的数组 fmt.Println(len(slice2), cap(slice2)) // 6 6 //我们修改一下slice2 slice2[1] = 100 fmt.Println(arr) //[1 100 3 4 5 6] //当我们修改了slice2,发现arr的值也被改变了,说明切片是一个指向数组的指针,修改切片等于修改数组 //我们再来看一个有趣的例子 s1 := arr[1:3] fmt.Println(s1) //[100 3] //这里的s1里面只有两个元素,但是我们取了1: 4 s2 := s1[1:4] fmt.Println(s2) //[3 4 5],这里打印了3, 4, 5 //为什么会发生这种现象 /* arr: 1 100 3 4 5 6 s1: 100 3 s2: 3 4 5 上面说了,切片是底层数组的一个view,s1和s2都是view这个arr,是可以扩展的 可以向后看,但是不可以向前看,s2向前最多也就只能看到100,不可能看到100前面的1, 如果指定s1[1:8]那么显然就不行了,因为底层数组只有6个元素,索引最大的才是5,而且s1[0]相当于arr[1],所以s1最多就是s1[:5] */ var arr2 = [5]int{1,2,3,4,5} var s3 = arr2[:3] fmt.Println(s3) //[1 2 3] //同理我们这里打印s3[0: 5]也没有问题,因为s3view底层数组arr2,但如果是s3[4]就会越界,因为切片没有索引为4的元素 fmt.Println(s3[0: 5]) //[1 2 3 4 5] //之前不说数切片的长度在数组长度的范围内是可变的吗?怎么变呢?可以使用append s3 = append(s3, 500)//我往s3的末尾添加一个500 fmt.Println(s3) //[1 2 3 500] fmt.Println(arr2) // [1 2 3 500 5] //首先s3很好理解,但是arr2为什么变了。 //我们往s3的末尾添加一个500,s3又view这个arr2,等价于s3=arr2[:4],s3[3]=500 //而且append会有一个返回值,而且可以一次性添加多个元素,append(s, element1, element2......) //如果我想把一个切片里的元素全部添加进去该怎么办?在python中可以使用*,在go中可以使用... append_slice := []int{100,200} s3 = append(s3, append_slice...) fmt.Println(s3) //[1 2 3 500 100 200],此时我们动态添加已经超过了底层数组的容量 //我们来看看底层数组 fmt.Println(arr2) //[1 2 3 500 5] //底层数组没有变化,因为我们一次性添加两个元素,已经超过了底层数组的长度。 //此时go会自动分配一个更大的数组,让s3去view,换句话说此时的s3已经不再view arr2,至于s3view的数组在什么地方,这个就不得而知了。 //此时再改变s3 s3[0] = 123456 fmt.Println(arr2) //[1 2 3 500 5] //会发现arr2依旧没有改变,因为s3已经不再看arr2这个数组了,因此s3改变只会影响那个不知道在什么地方的数组,不会影响arr2 //创建切片,还有另一种方式,使用make([]type, len, cap) s4 := make([]int, 4) //如果不写cap,那么默认和len一致 fmt.Println(s4) // [0 0 0 0] fmt.Println(len(s4),cap(s4)) //4 4 s4 = append(s4, 1, 2) fmt.Println(len(s4),cap(s4)) //6 8 s4 = append(s4,3,4) fmt.Println(len(s4),cap(s4)) //8 8 s4 = append(s4, 4) fmt.Println(len(s4),cap(s4)) //9 16 //可以看到一旦满了,就会扩大一倍 //那么如何遍历数组或者切片呢?使用for循环 girls := []string{"古明地觉", "雾雨魔理沙", "芙兰朵露斯卡雷特"} for i:=0;i<len(girls);i++{ fmt.Println(girls[i]) /* 古明地觉 雾雨魔理沙 芙兰朵露斯卡雷特 */ } for _,name := range girls{ fmt.Println(name) /* 古明地觉 雾雨魔理沙 芙兰朵露斯卡雷特 */ } }
以上是关于go的高级数据与结构类型的主要内容,如果未能解决你的问题,请参考以下文章
go语言学习笔记 — 基础 — 高级数据类型 — 数据容器 — 切片:切片内部结构
go语言学习笔记 — 基础 — 高级数据类型 — 派生类型:指针(pointer)数据容器函数(func)结构体(struct)通道(channel)
go语言学习笔记 — 基础 — 高级数据类型 — 结构体:初始化结构体的成员变量