逐步学习Go-集合(Arrays, Slices,Map,Set)

内容纲要

概述

go提供了以下三类集合:

  1. 数组(Arrays)
  2. 切片(Slices)(动态数组)
  3. Map
  4. Set不是Go提供的集合,可以使用Map来实现Set(Java也是通过Map实现的Set)

数组(Arrays)

数组的长度是固定的,定义完成后是无法改变长度的。下面看一下数组的定义:

var array [5]int

上面代码定义了一个5个元素的数组,go中数组不像Java中定义后要new,go默认就已经分配了空间,并把元素设置了零值。比如:我现在循环打印这个数组就,我们就会知道每个元素都是0:

for i := 0; i< len(array); i++ {
    fmt.Println(arr[i])
}

file

数组元素初始值

那其他类型的数组的初始值是什么?go中有很多类型,我们来给一个列表:

  • 数值类型(如int, float等):0
  • 布尔类型:false
  • 字符串类型:"" (空字符串)
  • 指针:nil
  • 接口(interface):nil
  • 切片(slice):nil
  • 映射(map):nil
  • 函数:nil
  • 通道(channel):nil
  • 结构体(struct):所有字段都是其对应数据类型的零值

数组操作

array := [5]int{1, 2, 3, 4, 5}

不能删除。

// 基于索引查值
value := array[2] 

// 查询数组长度
len(array)

// 遍历for循环
for i := 0; i < len(array); i++ {
    value := array[i]
}

// 遍历range
for i, value := range array {
    println("index: %d, value: %d", i, value)
}

// 修改第二个元素
array[1] = 10 

关于数组的增,查和改操作大家可以去搜搜工具类。

切片(Slices)(动态数组)

切片就是一个数组,可以根据情况进行扩缩容(类似于Java ArrayList)。切片底层就是一个数组。

操作

创建一个切片,和数组方式差不多:[]int,在[]中不指定长度就好了;指定了就是数组了。

// 创建并初始化
slice := []int{1, 2, 3, 4, 5}

// 创建一个空的
slice := make([]int, 5)

添加元素需要使用append函数

slice = append(slice, 6)

切片支持删除,删除也是使用append,但是也可以通过创建新切片来完成

    // 创建一个新slice,不包含第一个元素
    slice1 := slice[1:]

    // 删除第一个元素
    slice = append(slice[1:])
    for i, value := range slice1 {
        println("index: %d, value: %d", i, value)
    }

    // 删除第二个元素:2
    slice = append(slice[:1], slice[2:]...)
    for i, value := range slice {
        fmt.Printf("index: %d, value: %d\n", i, value)
    }

        // 删除第二和第三个元素:2,3,
    slice = append(slice[:1], slice[3:]...)
    for i, value := range slice {
        fmt.Printf("index: %d, value: %d\n", i, value)
    }

删除多个就是更改你的删除范围(数组索引值)就好了,但是你的索引超过了数组的最大索引范围就要报错了,就是数组越界。
删除中间一个元素:
file

删除多个元素:
file

数组越界:
file

读取切片的元素和数组是一样的。

value := slice[2]

修改切片是和数组一样的。

slice[1] = 10

切片和数组的区别

下面是一个展示数组 (Array) 和切片 (Slice) 在 Go 语言中的主要区别的表格:

特性 数组 (Array) 切片 (Slice)
长度 长度固定,创建时就要指定大小 长度可以动态变化,可以在运行时添加和删除元素
动态性 静态的 动态的
内存占用 较小 大小在运行时可能会改变
定义方式 var arr [n]T var slice []T
创建方式 arr := [n]T{t1, t2, t3, …} slice := []T{t1, t2, t3, …} 或slice := make([]T, len, cap)
初始值 取决于数组元素类型 nil

Map

Map就是键值对咯,像Java中的HashMap,python的字典之类的。

go中的这个map不是协程安全的,如果想要使用协程安全的,可以使用sync包中的map。

操作

map使用make函数来创建或者直接初始化键值对创建。
make函数基本啥都能造。

// 创建一个空的map
m := make(map[string]int)

// 创建并初始化
m := map[string]int{
    "1": 1,
    "2": 2,
}

// 添加键值对
m["3"] = 3

删除用delete函数,第一参数是map,第二个参数是key。

delete(m, "1")

// 判断是否存在
value, exists := m["2"] 
if exists {
    fmt.Println(value) 
} else {
    fmt.Println("key不存在.")
}

// 遍历
for key, value := range m {
    fmt.Printf("key: %s, values: %d.", key, value)
}

修改map的数组和python的字典类似:

m["1"] = 10

Set

Set go中并没有直接提供,我们使用map就可以很快的造一个Set。

type Set struct {
    elements map[interface{}]bool
}

func NewSet() *Set {
    return &Set{
        elements: make(map[interface{}]bool),
    }
}

// Add元素到set.
func (set *Set) Add(element interface{}) {
    set.elements[element] = true
}

// Remove元素从set.
func (set *Set) Remove(element interface{}) {
    delete(set.elements, element)
}

// Exists检查元素是否在set中.
func (set *Set) Exists(element interface{}) bool {
    _, exists := set.elements[element]
    return exists
}

//读取所有元素
func (set *Set) Elements() []interface{} {
    keys := make([]interface{}, len(set.elements))
    i := 0
    for key := range set.elements {
        keys[i] = key
        i++
    }
    return keys
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部