同事被Go多维切片问题难住 我分分钟把他教会

简介: 同事被Go多维切片问题难住 我分分钟把他教会

/ Go 语言多维切片完全攻略 /

切片是 Go 语言中一个非常重要也比较特殊的类型。除了基本的一维切片外,Go 语言还支持多维切片,即切片的元素也可以是切片。理解和应用多维切片对于提高 Go 语言编程能力非常关键。

本文将全面介绍 Go 语言多维切片相关的知识,包括:

  1. 二维切片基本介绍
  2. 多维切片声明
  3. 多维切片初始化
  4. 多维切片访问
  5. 从数组生成多维切片
  6. 不规则多维切片
  7. 多维切片的长度和容量
  8. 多维切片的复制
  9. 多维切片的遍历
  10. 多维切片的应用

对多维切片有全面的了解,可以帮助我们写出更灵活高效的 Go 语言代码。


1

 

1. 二维切片基本介绍

二维切片是最常见的多维切片,定于方式是[]Type

可以把二维切片看成是一个切片的切片,每个内部切片的长度可以不同。这一点和二维数组不同,数组的每个内层长度必须相同。

举个例子,一个二维切片定义:

[][]int

访问第一个元素:

slice[0]

二维切片允许非统一长度,类似于链表。


2

 

2. 多维切片声明

下面是多维切片常见的声明方式:

var sl1 []int
var sl2 [][]int 
var sl3 [][][]int

一维切片声明时只有一个[],二维三维类推,每个[]表示一层切片。

所以[][][]int就是一个三维int切片。

切片初始化时也可以用类似语法:

sl3 := [][][]int{}

3

 

3. 多维切片初始化

下面是多维切片初始化的各种方式:

// 空切片
var sl = [][]int{}
// 使用make初始化,只设置长度
sl = make([][]int, 2)
// 设置长度和容量
sl = make([][]int, 2, 4) 
// 含有元素的切片
sl = [][]int{{1,2},{3,4}}
// 使用new初始化
sl = new([][]int)

make 可以指定长度和容量,用来初始化切片。

需要注意的是,多维切片每个内层切片的长度可以不同。


4

 

4. 多维切片访问

多维切片访问需要按层级顺序进行:

sl := [][]int{{1,2},{3},{4,5,6}}
sl[0] // 获取第一层切片 
sl[0][0] // 获取第二层的第一个元素
sl[1][0] // 第二层切片的第一个元素

切片索引从 0 开始,需要按顺序进行。

检查切片边界可以避免出错:

if len(sl) > i && len(sl[i]) > j {
  sl[i][j]
}

5

 

5. 从数组生成多维切片

可以通过从数组切割来生成多维切片:

arr := [2][3]int{{1,2,3},{7,8,9}}
sl := arr[:1][:2] // 获取二维切片
fmt.Println(sl) // [[1 2]]

需要按顺序切割获得多维切片。

这样可以构建不均匀长度的切片。


6

 

6. 不规则多维切片

举个不规则多维切片的例子:

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

不同内层切片长度不一样,这在多维切片中是允许的。

可以基于不规则切片构建特定的数据结构,比如链表。

需要注意切片边界,否则会导致访问错误。


7

 

7. 多维切片长度和容量

多维切片也有长度和容量的属性:

sl := [][]int{
  {1, 2, 3},
  {4, 5},
}
len(sl) // 2,外层切片长度
cap(sl) // 2,外层切片容量 
len(sl[0]) // 3,内层切片长度
cap(sl[0]) // 3,内层切片容量

    内层切片长度可能不相同,但外层切片长度固定。


    8

     

    8. 多维切片的复制

    多维切片之间进行复制也会复制外层和内存引用:

    func main() {
      s1 := [][]int{{1}, {2}}
      s2 := make([][]int, 2)
      copy(s2, s1)
      s2[0][0] = 200
      fmt.Println(s1) // [[200], [2]]
    }

    可以看到 s1 也被修改了,因为两个切片引用同一内存。

    需要深度复制每个内层切片的元素,而不是直接复制引用。


    9

     

    9. 多维切片的遍历

    可以通过嵌套 for 循环来遍历多维切片:

    for i := range sl {
      for j := range sl[i] {
        println(sl[i][j]) 
      }
    }

    或者使用 for range 代替内层 for:

    for i := range sl {
      for j, v := range sl[i] {
        println(j, v)
      }
    }

    这类似遍历二维数组,需要按层级顺序进行访问。


    10

     

    10. 多维切片应用

    多维切片有很多实际的应用场景:

    • 矩阵运算
    • 嵌套数据结构
    • 分层数据
    • 树结构
    • 网格结构
    • 图像像素处理

    例如可以用二维切片实现矩阵:

    // 初始化一个二维矩阵
    matrix := [][]float32{  
      {1, 2, 3},
      {4, 5, 6},
    } 
    // 矩阵乘法
    func mult(m1, m2 [][]float32) [][]float32 {
      // 矩阵乘法逻辑实现
      ...
    }

    再如表示分层或嵌套数据:

    tree := [][]string{
      {"root"},
      {"first", "second"},
      {"foo", "bar"},
    }

    多维切片非常灵活,可以表示多种复杂数据结构。


    11

     

    总结

    通过本文全面讲解,可以深入理解 Go 语言多维切片的各方面知识,包括声明、初始化、访问、遍历等用法技巧。多维切片是一个非常强大的语言特性,可以实现各种嵌套和层次的数据结构。充分利用多维切片可以让我们的 Go 语言编程更加高效和富有表现力。


    目录
    相关文章
    |
    2月前
    |
    Go
    Go 中使用切片来实现动态数组的功能
    Go 中使用切片来实现动态数组的功能
    |
    2月前
    |
    存储 监控 Go
    【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
    【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
    46 3
    |
    2月前
    |
    Go
    go语言数组与切片
    go语言数组与切片
    31 0
    |
    13天前
    |
    Go
    Go 1.21的新特性: 切片和映射
    Go 1.21的新特性: 切片和映射
    |
    14天前
    |
    存储 Go
    go 切片长度与容量的区别
    go 切片长度与容量的区别
    |
    22天前
    |
    存储 Go
    go切片和指针切片
    go切片和指针切片
    14 2
    |
    5天前
    |
    监控 Serverless Go
    Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
    Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
    |
    6天前
    |
    人工智能 Go
    go切片参数传递用值还是指针
    go切片参数传递用值还是指针
    13 0
    |
    13天前
    |
    存储 Go 开发者
    在Go中对切片/数组求和的多种方法
    在Go中对切片/数组求和的多种方法
    |
    2月前
    |
    Go
    Go 语言是如何实现切片扩容
    Go 语言是如何实现切片扩容