专栏首页Golang语言社区Go语言的复合数据类型

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)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 转--Golang语言--复合数据

    1、array 数组的类型格式为单个数据单元类型+长度构成,如 [2]int,其中 [2] 代表数组的长度,而 int 代表每个单元都是整形。 数组的元素操作也...

    李海彬
  • Go语言中的Array、Slice、Map和Set使用详解

    Array(数组) 内部机制 在 Go 语言中数组是固定长度的数据类型,它包含相同类型的连续的元素,这些元素可以是内建类型,像数字和字符串,也可以是结构类型,元...

    李海彬
  • Go语言中的Array、Slice、Map和Set使用详解

    Array(数组) 内部机制 在 Go 语言中数组是固定长度的数据类型,它包含相同类型的连续的元素,这些元素可以是内建类型,像数字和字符串,也可以是结构类型,元...

    李海彬
  • Dimple在左耳听风ARTS打卡(二十三)

    所谓ARTS:每周至少做一个LeetCode的算法题;阅读并点评至少一篇英文技术文章;学习至少一个技术技巧;分享一篇有观点和思考的技术文章。(也就是Algori...

    程序员小跃
  • BucketSort-桶排序-计数排序

    sr
  • 对数器应用-SelectionSort-选择排序

    sr
  • 七种常用排序算法的java实现

    曼路
  • Android DSelectorBryant 单选滚动选择器的实例代码

    单选滚动选择器、diy丰富、有阻尼效果、简单美观、触摸or点击模式 (Rolling Selector, Diy Rich, Damping Effect, S...

    砸漏
  • 洛谷P4013 数字梯形问题(费用流)

    梯形的第一行有 mmm 个数字。从梯形的顶部的 mmm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。

    attack
  • 【AtCoder - 2300】Snuke Line(树状数组)

    每隔d站停一次的列车,一定能买到购买区间的长度≥d的纪念品。 长度比d小但包含了d的倍数的纪念品也可以买到。 所以,如果按长度给纪念品排序,用树状数组维护长...

    饶文津

扫码关注云+社区

领取腾讯云代金券