Go 数据类型(续)— array、slice、map

abc123man · · 7473 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go 将常用的数据结构数组(array)、切片(slice)、映射(map)实现为内置类型。可以利用 array 在列表中进行多个值的排序,或者使用更加灵活的:slice。字典或哈希类型同样可以使用,在 Go 中叫做 map。

1、array

  • 数组定义

    array 定义 [n]<type> ,n 为数组长度,长度是类型的一部分,定义后不能改变数组大小;<type> 为数组元素类型,对数组的存取和 C 语言一样,都是通过 [ ] 加索引来完成。

    var arr [10]int // 定义长度为 10 的整型数组
    arr[0] = 15 // 赋值
    arr[9] = 33
    ib := arr[0] // 读取
  • 数组初始化

    按照 Go 固定,声明的变量未初始化是默认赋值为其类型的 0。数组也一样,未初始化的数组自动赋值为 0。数组的初始化可以在声明时使用大括号加值来完成,如果每个元素都给定初值,可以省略大小使用 ... 来代替,则编译器会自动计算数组大小。

    var a0 [10]int // 初始化为 0
    a := [3]int{1, 2, 4} // 声明并初始化话
    // 等价于 a := [...]int{1, 2, 4}
    
    /* 多维数组 */
    b := [2][2]int{ [2]int{1, 2}, [2]int{3, 4} }
    // 等价于 b := [2][2]int{ [...]int{1, 2}, [...]int{3, 4} }
    // 2010-10-27 后的新版本中可以使用下面更简单的形式
    b := [2][2]int{ {1, 2}, {3, 4}}

注意:数组是值类型的:将一个数组赋值给另一个数组,会复制所有的元素。尤其是当向函数内传递一个数组的时候,它会获得一个数组的副本,而不是数组的指针

2、slice

slice 与 array 接近,但是在新的元素加入的时候可以增加长度。 slice 总是指向底层的一个 array。 slice 是一个指向 array 的指针,这是其与 array 不同的地方; slice 是引用类型, 这意味着当赋值某个 slice 到另外一个变量,两个引用会指向同一个 array。如果一个函数需要一个 slice 参数,在其内对 slice 元素的修改也会体现在函数调用者中,这和传递底层的 array 指针类似。

  • slice 创建

    slice 可以使用内置函数 make 创建。它总是与一个固定长度的 array 成对出现。slice 与底层的 array 并无区别。

    sl := make([]int, 10) // 创建保存有 10 个元素的 slice
    
    var arr [m]int // 创建数组,假设 m > 4
    slice := arr[0:n] //创建指向此数组的 slice,长度为 n, 索引为:0 ~ n-1
    /* 长度和容量 */
    len(slice) == n
    cap(slice) == m
    len(arr) == cap(arr) == m
    
    /* 选择一定区间元素创建 slice */
    sl1 := arr[1:5] // 索引为 1 ~ 4
    sl2 := arr[:5]  // 索引为 0 ~ 4
    sl3 := arr[2:]  // 索引为 2 ~ m-1
    sl4 := arr[:]   // 索引为 0 ~ m-1

    array 与 slice 对比

    给定一个 array 或者其他 slice,一个新 slice 通过 a[i:j] 的方式创建。这会创建一个新的 slice,指向变量 a,索引为 i~ j-1 (半闭半开区间)。长度为 j - i。省略 i 则默认索引从 0 开始,省略 j 则默认索引结束于数组最后一个元素,i 和 j 都省略则 slice 取数组全部元素。i 和 j 都不能超出数组索引的范围,否则会出现运行时错误。

  • 扩展 slice

    扩展 slice 可以使用内建函数 append 和 copy。
    来自文档的描述:
    函数 append 向 slice s 追加零值或其他 x 值,并且返回追加后的新的、与 s 有相同类型的 slice。如果 s 没有足够的容量存储追加的值, append 分配一个足够大的、新的 slice 来存放原有 slice 的元素和追加的值。因此,返回的 slice 可能指向不同的底层 array

    s0 := []int{0, 0}
    s1 := append(s0, 2) // 追加一个元素
    s2 := append(s1, 3, 5, 7) // 追加三个元素
    s3 := append(s2, s0...) // 追加一个 slice,**注意此处的三个点**

    函数 copy 从源 slice src 复制元素到目标 dst,并且返回复制的元素的个数。源和目标可能重叠。复制的 数量是 len(src) 和 len(dst) 中的最小值。

    var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    var s = make([]int, 6)
    n1 := copy(s, a[0:]) // n1 == 6, s == []int{0, 1, 2, 3, 4, 5},多余的不复制
    n2 := copy(s, s[2:]) // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}

3、map

Go 将 map 作为内建类型。一般定义 map 的格式为:

map[<key type>]<value type>

例如定义一个map 表示每月对应的天数:

monthdays := map[string]int {
    "Jan": 31, "Feb": 28, "Mar": 31,
    "Apr": 30, "May": 31, "Jun": 30,
    "Jul": 31, "Aug": 31, "Sep": 30,
    "Oct": 31, "Nov": 30, "Dec": 31, ← 逗号是必须的
}

只声明一个 map 而不进行初始化时,需要使用内置函数 make。如

monthdays := make(map[string]int)

对 map 的存取使用方括号加键的形式:

monthdays["Undecim"] = 30 // 添加一个元素
monthdays["Feb"] = 29 // 修改值
jan := monthdays["Jan"] // 取键为 "Jan" 的值

检验 map 中是否存在某个键,可以使用逗号 ok 形式:

val, ok := monthdays["Jan"] // 若键 "Jan" 存在,ok == true

删除 map 中的某个元素,使用 delete(map, key)

delete(monthdays, "Mar") // 删除键为 "Mar" 的元素

4、遍历 array、slice、map

可以使用 range 对 array、 slice、 string 或者 map 进行循环遍历,每次调用,它都会返回一个键和对应的值。

// 计算一年的天数
// 使用 range 对 map 进行遍历
year := 0
for _, days := range monthdays { // 键没有使用,因此用 _, days
    year += days
}

版权声明:本文为博主原创文章,未经博主允许不得转载。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:abc123man

查看原文:Go 数据类型(续)— array、slice、map

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

7473 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传