Go语言入门总结(四)- 数组、切片和映射

数组、切片和映射

1.数组

对于数组的定义以及初始化,可以分为以下三种方式:

    //1.先定义,再赋值
    var list1 [8]string
    list1[0] = "第一个值"
    //没有初始化赋值的部分默认会用零值填充,string类型的零值为空的字符串
    
    //2.赋值并初始化
    var list2 = [8]string{"第一个值","第二个值"}
    list3 := [8]string{"第一个值","第二个值"}
    
    //3.不设置数组大小,让数组根据内容自动设置大小
    var list4 = [...]string{"第一个值","第二个值"}
    //等价于  var list4 = [2]string{"第一个值","第二个值"}

数组的循环变量,可以使用以下2种方式:

func main() {
    var list = [8]string{"第一个值","第二个值"}

    //最常见的循环方式
    for i := 0;i < len(list);i++{
        fmt.Println(list[i])
    }

    //使用range实现循环
    for i,value := range list{
        fmt.Printf("index :%d , value : %s\n" ,i,value)
    }
}

对于数组来说,无论是将数组赋值给新的变量还是将它传递给函数,都会产生一个完整的数组副本。
所以传递数组给一个函数,在函数里面修改数组的值仅仅只是修改了原始数组的一个副本。

2.切片

切片使用:将元素进行区间取值。其中取值的数字代表的下标相当于前闭后开区间。
切片的如果是从0开始,':'前面的值也可以不写。如果取值范围是到结尾,那么':'后面的值可以不写。
切片里面元素值的改变是不会对切片数据原始来源的数据产生影响的。

func main() {
    var list = [8]int{0,1,2,3,4,5,6,7}

    //切片
    list1 := list[0:4]
    list2 := list[4:6]
    list3 := list[6:8]

    fmt.Println(list1,list2,list3)//打印结果为[0 1 2 3] [4 5] [6 7]

    list5 := list[:4] //值的结果等价于list1
    list6 := list[6:] //值的结果等价于list3
}

一般来说,函数传递不会传递数组,而是传递切片。

func main() {
    var list = [8]int{0,1,2,3,4,5,6,7}
    var list2 = [2]int{0,1}
    var list3 = []int{0,1,2}
    var list4 = []int{0,1,2,4}
    
    //list 与 list2 是不同的类型,但是 list3 与 list4 是同一类型
    setList(list3)
    setList(list4)
}

func setList(num []int){
    
}

相比于有固定大小的数组,切片是一个可以根据需要,按需增长的。
这就涉及到切片的长度和容量了。

func main() {
    var list = []int{0,1,2,4}
    fmt.Printf("list 长度为 %d ,容量为 %d ,内容为 %v\n",len(list),cap(list),list)
    //输出结果为
    //list 长度为 4 ,容量为 4 ,内容为 [0 1 2 4]

    list2 := list[1:3]
    fmt.Printf("list2 长度为 %d ,容量为 %d ,内容为 %v",len(list2),cap(list2),list2)
    //输出结果为
    //list2 长度为 2 ,容量为 3 ,内容为 [1 2]
}

为什么list2输出的结果容量为3呢?
因为切片取值的时候,默认会切掉前面的部分,后面部分是隐藏的,虽然无法通过下标取值的方式取值到隐藏容量里面的内容,但是数据其实都还是存在的。

append函数
切片里面的内容可以通过append函数对数据进行追加。
每次超过数组容量以后,切片会自动扩充容量,容量为当前数组的2倍。并且扩容后的切片和原始的切片指向的是不同的数组。但是如果容量没有改变,那么他们指向的就是相同的数组,修改其中的数据会对同一容量的切片产生影响。

func main() {
    var list = []int{0,1,2,4}
    list2 := append(list,5)
    list3 := append(list2,6,7)

    fmt.Printf("list2 长度为 %d ,容量为 %d ,内容为 %v",len(list2),cap(list2),list2)
    //输出结果为
    //list2 长度为 5 ,容量为 8 ,内容为 [0 1 2 4 5]

    fmt.Printf("list3 长度为 %d ,容量为 %d ,内容为 %v",len(list3),cap(list3),list3)
    //输出结果为
    //list3 长度为 7 ,容量为 8 ,内容为 [0 1 2 4 5 6 7]

    list2[0] = -1
    fmt.Println(list,list2,list3)
    //输出结果为
    //[0 1 2 4] [-1 1 2 4 5] [-1 1 2 4 5 6 7]
}

因为隐藏空间的内容不会被抹去,所以切片提供了一个三索引切分的方法,用来设置切片的后面的截取index在哪里。

func main() {
    var list = []int{0,1,2,3,4,5,6,7,8,9}
    list2 := list[1:5]
    list3 := list[1:5:5]

    fmt.Printf("list2 长度为 %d ,容量为 %d ,内容为 %v\n",len(list2),cap(list2),list2)
    //输出结果为
    //list2 长度为 4 ,容量为 9 ,内容为 [1 2 3 4]

    fmt.Printf("list3 长度为 %d ,容量为 %d ,内容为 %v\n",len(list3),cap(list3),list3)
    //输出结果为
    //list3 长度为 4 ,容量为 4 ,内容为 [1 2 3 4]
}

make函数
使用make函数可以对数据进行初始化的长度和容量分配。好处是可以避免额外的内存分配和数组复制操作。

func main() {
    var list = make([]int,0,10)
    var list2 = make([]int,10)//这种初始化时默认会用类型的零值作为数据填充的

    fmt.Printf("list 长度为 %d ,容量为 %d ,内容为 %v\n",len(list),cap(list),list)
    //输出结果为
    //list 长度为 0 ,容量为 10 ,内容为 []

    fmt.Printf("list2 长度为 %d ,容量为 %d ,内容为 %v\n",len(list2),cap(list2),list2)
    //输出结果为
    //list2 长度为 10 ,容量为 10 ,内容为 [0 0 0 0 0 0 0 0 0 0]
}

3.映射(map)

map的声明方式

//  变量名   = map[key的类型] 值的类型 {}
var mapItem = map[int] string{}

简单的例子:

func main() {
    //  变量名   = map[key的类型] 值的类型 {}
    var mapItem = map[int] string{
        1:"张三",
        2:"李四",
    }

    fmt.Println(mapItem)
    //输出: map[1:张三 2:李四]
}

如果访问的键不存在与map之中,那么go语言会根据值类型返回相应的零值。
当然对于这种情况,go语言也提供了方法供你进行判断是否存在再来处理,而不是直接输出零值。

func main() {
    //  变量名   = map[key的类型] 值的类型 {}
    var mapItem = map[int] string{
        1:"张三",
        2:"李四",
    }

    if key,has := mapItem[3];has{
        fmt.Println(key)
    }else {
        fmt.Println("不存在")
    }
}

map与其他普通的类型不同,map被赋值给其它变量或者传递给某个函数的参数时,对其中一个修改都会影响其它的map,因为它们共享底层数据。
map也可以使用make函数初始化分配空间。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354