Go语言的复合数据类型

Go语言的复合数据类型是基础数据类型的组合,主要包括四个数组,切片(slice),map和结构体。 数组和结构体的大小是固定大小的,数组的元素类型是固定的,结构体的元素类型是不固定。 map和slice是动态的数据结构,它们将根据需求动态的增长。 数组 数组顾名思义就是同一类资源或者数据的集合。下面主要介绍对数组的操作: 数组的初始化 var arr [3]int //默认初始化0 var q [3]int = [3]int{1,2,3} q := [...]int{1,2,3} q := [...]int{90:-1}//key和value的赋值方式,下表90的值为-1,数组长度为91 复制代码 数组的访问 可以使用数组下标来访问数组中的元素。与C语言相同,数组下标从0开始,len(array)-1 则表示最后一个元素的下标。下面的示例遍历整型数组并逐个打印元素内容: q := [...]int{1, 2, 3, 4} for i, value := range q { fmt.Println(i, value) } 复制代码 数组可以直接进行比较,当数组内的元素都一样的时候表示两个数组相等。 arr1 := [3]int{1, 2, 3} arr2 := [3]int{1, 2, 3} arr3 := [3]int{1, 2, 4} fmt.Println(arr1 == arr2, arr1 == arr3) //true,false 复制代码 数组可以作为函数的参数传入,但由于数组在作为参数的时候,其实是进行了拷贝,这样在函数内部改变数组的值,是不影响到外面的数组的值得。 func ArrIsArgs(arr [4]int) { arr[0] = 100 } q := [...]int{1, 2, 3, 4} ArrIsArgs(q) 如果想要改变: func ArrIsArgs(arr *[4]int) { arr[0] = 100 } q := [...]int{1, 2, 3, 4} ArrIsArgs(&q) 但一般都是用切片来解决这个问题,而不是用数组。 切片 切片和数组很相似,只是它的长度并不是固定的,也就是定义的时候[ ]T内不需要指定长度。 数组和slice关系非常密切,一个slice可以访问数组的部分或者全部数据,而且slice的底层本身就是对数组的引用。 一个Slice由三部分组成:指针,长度和容量。内置的len和cap函数可以分别返回slice的长度和容量 首先我们来看slice的创建方式: 创建slice主要两种:1.基于数组创建。2.直接创建 基础数组创建: 数组arrVar和sliceVar里面的地址其实是一样的,也就是说如果你改变sliceVar里面的变量,那么arrVar里面的变量也会随之改变。 2.直接创建 可以使用内置的make()函数来创建。事实上还是会创建一个匿名的数组,只是不需要我们来定义。 对于为什么说slice其实和数组是一个地址那,看下面这张图: 3.动态的增减元素 前面说过,slice是可以动态扩展的。但slice的动态扩展是有代价的,也就是说如果在确定大小的前提下,最好是设置好slice的cap大小,看个经典的例子: 可以看到,当slice的的容量等于len的时候,cap是翻倍了。append的底层原理就是当slice的容量满了的时候,重新建立一块内存,然后将原来的数据拷贝到新建的内存。所以说容量的扩充是存在内存的建立和复制的。该过程将会影响到系统的运行速度。 append 也可以将两个slice拼接起来,但格式有所不同: 两个slice也可以直接进行内容的复制,copy函数: 4.作为形参使用 要想搞清楚slice我们需要看一下slice作为函数参数的使用方式,看一下下面的几个例子: eg1 的结果是[0 1 2 3 4 5 6 7],eg2的结果是[0 0 0 0 0 0 0 0]。来分析两个实例的不同,如果和你想的不一样,那么就证明你对slice的理解是有问题的(我也纠结了比较久o(╯□╰)o) 首先分析一下第一个用例TestSLice(myslice1[:0]),这个的意思其实就是将一个新的slice作为参数传给函数,新的slice指向的是myslice1的第0个元素的地址,这时候你可以测试一下myslice1[:0]这个东西的cap和len,数值分别为8和0,然后你在函数里面append的时候实际上是对新的slice进行了操作,但由于外面的函数的参数的slice和myslice1又是同一个地址,所以外面的数值是被改变了的。 再来分析第二个实例,第二个实例直接把myslice1传给了函数,这其实是复制了一个slice的,在函数里面append的时候当你的len大于cap值得时候,这时候返回的是一个新的地址。所以外面的变量是不会变化的。全是默认值0 那么我们想直接改变外面的slice怎么办?答案就是指针,在GO语言里面你想修改什么就传什么的指针。 对于SLICE的应用基本就可以到这里结束了,大家可以多测试一下Slice的使用。 在Go语言中,所有的函数参数都是值拷贝传入的,函数参数将不再是函数调用时的原始变量 map 在C++/java中,map 一般都是封装在库里面的,但在GO语言中map可以直接使用。作为Key-value的数据结构,map就是对哈希表的引用。 1.声明 var myMap map[string] PersonInfo myMap是声明的变量名,sting是对应的Key的类型,PeesonInfo是value的类型。 2.创建 创建map使用的是GO语言内置的make()来创建的。 创建一个容量固定的MAP 创建初始化MAP 3.元素的删除 对于map的元素的删除,可以采用内置的delete函数 如果你后面传入的key不存在,那么调用不会产生什么错误,但如果myMap是nil那么就会抛出异常了。 4.元素的查找 在map中传统的做法是: 1.声明一个变量为空 2.将map中获得的值保存到变量中 3.判断是否为空。 但这种做法过于复杂,可以采用下面的方式来实现: value,ok := myM ap["1234"] if ok{//代表找到了 //代码处理模块 } delete(myMap,"123") mymap1 := map[string]int{"hello": 1, "world": 2} myMap = make(map[string] Personinfo,100) myMap = make(map[string] Personinfo) func TestSLice3(myslice *[]int) { for i := 0; i < 8; i++ { *myslice = append(*myslice, i) } } myslice1 := make([]int, 0, 8) TestSLice3(&myslice1) func TestSLice(myslice []int) { for i := 0; i < 8; i++ { myslice = append(myslice, i) } } eg1: myslice1 := make([]int, 8, 8) TestSLice(myslice1[:0]) fmt.Println(myslice1) //结果是什么? eg2: myslice1 := make([]int, 8, 8) TestSLice(myslice1 ) fmt.Println(myslice1) //结果是什么哪? slice1 := []int{1, 2, 3, 4, 5} slice2 := []int{5, 4, 3} copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中 copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置 oldSlice := []int{1, 2, 3, 4, 5} oldSlice2 := []int{6, 7, 8, 9, 10} oldSlice = append(oldSlice, oldSlice2...) //必须加三个... func TestAppend() { var slice []int for i := 0; i < 10; i++ { slice = append(slice, i) fmt.Printf("%d cap = %d t%v\n", i, cap(slice), slice) } } output: 0 cap = 1 t[0] 1 cap = 2 t[0 1] 2 cap = 4 t[0 1 2] 3 cap = 4 t[0 1 2 3] 4 cap = 8 t[0 1 2 3 4] 5 cap = 8 t[0 1 2 3 4 5] 6 cap = 8 t[0 1 2 3 4 5 6] 7 cap = 8 t[0 1 2 3 4 5 6 7] 8 cap = 16 t[0 1 2 3 4 5 6 7 8] 9 cap = 16 t[0 1 2 3 4 5 6 7 8 9] myslice1 := make([ ]int,5)//创建一个元素个数5的slice,cap也是5 myslice2 := make([ ]int,5,10)//创建一个元素个数5的slice,cap是10 myslice3 := [ ]int{1,2,3,4}//创建一个元素个数为4的slice,cap是4 var slice []int //创建一个空的slice,cap和len都是0 arrVar := [4]int{1, 2, 3,4} sliceVar := arrVar[1:3]

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2017-08-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

Go基础系列:struct和嵌套struct

struct定义结构,结构由字段(field)组成,每个field都有所属数据类型,在一个struct中,每个字段名都必须唯一。

19220
来自专栏一个爱吃西瓜的程序员

Python基础学习-函数

一:定义函数: ① 函数是带名字的代码块,用于完成具体的工作。 ② 函数使用关键字def来定义,最后,定义以冒号结尾。 ③ 每个函数后面都应紧跟一个文档字符串,...

39080
来自专栏Core Net

H5 data-*容易忽略的问题

36260
来自专栏积累沉淀

JavaScript正则表达式

什么是正则表达式? 正则表达式也叫做匹配模式(Pattern),它由一组具有特定含义的字符串组成,通常用于匹配和替换文本。 在JavaScript脚本中,利...

28450
来自专栏数据结构与算法

2277 爱吃皮蛋的小明

2277 爱吃皮蛋的小明  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 白银 Silver 题解  查看运行结果 题目描述 Descri...

30070
来自专栏阿炬.NET

Reflector、reflexil、De4Dot、IL指令速查表

34650
来自专栏Python

python ——面向对象进阶

1.staticmethod和classmethod staticmethod  静态方法: 让类里的方法,直接被类调用,就像正常的函数一样 宝宝,男 博博,女...

20970
来自专栏黑泽君的专栏

c语言基础学习07_指针

=============================================================================

26000
来自专栏容器云生态

awk-grep-sed简单使用总结(正则表达式的应用)

正则表达式: 匹配一组字符: #[ns]a.\.xls  //[]用于限定字符;“.”用于匹配任意字符; \.用于转义"." 匹配到s/na*.xls  [n...

29090
来自专栏Python小屋

小议Python列表和元组中的元素地址连续性

众所周知,在Python中字典和集合依赖元素哈希表来存储,并不存在传统意义上的所谓元素“顺序”,当然,如果需要一个有序的字典可以使用collections模块提...

366100

扫码关注云+社区

领取腾讯云代金券