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语言学习笔记 — 基础 — 高级数据类型 — 结构体:初始化结构体的成员变量

go基本数据类型

golang常用库包:缓存redis操作库go-redis使用(03)-高级数据结构和其它特性

4.Go语言高并发与微服务实战 --- Go 语言高级特性