Go 是否可以用括号分割内部矩阵?

Go 是否可以用括号分割内部矩阵?,go,matrix,slice,Go,Matrix,Slice,我正在修改矩阵上的周长值,然后尝试递归到内部值。我希望我能够使用类似于matrix[1:3][1:3]的东西访问内部值。事实并非如此,我对Go如何处理顺序括号的基本逻辑有点茫然 package main import ( "fmt" ) var m = [][]int{ []int{0, 1, 2, 3}, []int{4, 5, 6, 7}, []int{8, 9, 10, 11}, []int{12, 13, 14, 15}, } 我试图访问上述

我正在修改矩阵上的周长值,然后尝试递归到内部值。我希望我能够使用类似于
matrix[1:3][1:3]
的东西访问内部值。事实并非如此,我对Go如何处理顺序括号的基本逻辑有点茫然

package main

import (
    "fmt"
)

var m = [][]int{
    []int{0, 1, 2, 3},
    []int{4, 5, 6, 7},
    []int{8, 9, 10, 11},
    []int{12, 13, 14, 15},
}
我试图访问上述矩阵中的值5、6、9、10——“内部”矩阵

函数innerMatrix能够产生我期望的输出。我不明白为什么(1)
m[1:3][1:3]
没有同样的效果,(2)它似乎转化为
m[2:4]
。发生什么事了


当您在Go中创建子切片时,您可以将该子切片再次增长到原始切片的容量,例如:

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5}

    b := a[1:3]
    fmt.Printf("a[1:3]: %v\n", b)

    c := b[1:3]
    fmt.Printf("b[1:3]: %v\n", c)
}
哪些产出:

a[1:3]: [2 3]
b[1:3]: [3 4]
b: [2 3 4 5], a[1:5]               : [2 3 4 5]
c: [3 4 5]  , a[1:5][1:4]          : [3 4 5]
d: [4 5]    , a[1:5][1:4][1:3]     : [4 5]
e: [5]      , a[1:5][1:4][1:3][1:2]: [5]
请注意,
b
只有两个元素,但是我们可以创建第二个和第三个元素的片段,因为它作为子片段的片段的容量足够大,并且所有片段共享相同的底层数组。请参阅上“切片内部构件”一节中的最后一个示例

因此,在您的情况下,
m[1:3]
相当于:

var m1 = [][]int{
    []int{4, 5, 6, 7},   // second element of m
    []int{8, 9, 10, 11}, // third element of m
}
var m2 = [][]int{
    []int{8, 9, 10, 11},   // second element of m1
    []int{12, 13, 14, 15}, // "third" element of m1
}
因此,
m[1:3][1:3]
相当于
m1[1:3]
,相当于:

var m1 = [][]int{
    []int{4, 5, 6, 7},   // second element of m
    []int{8, 9, 10, 11}, // third element of m
}
var m2 = [][]int{
    []int{8, 9, 10, 11},   // second element of m1
    []int{12, 13, 14, 15}, // "third" element of m1
}
“第三个”元素的出现仅仅是因为
m
的容量大到足以容纳它,并且实际上包含它。如果
m
只有三个元素,就会引起恐慌

换句话说,
m[1:3][1:3]
在这里完全等同于
m[2:4]
,因为
m[1:3][1:3]
提供了
m[1:3]
的第二和第三个元素。使用图表可能更容易理解:

m            : []int{1, 2, 3, 4}
m[1:3]       : []int{   2, 3   }
m[1:3][1:3]  : []int{      3, 4}
m[2:4]       : []int{      3, 4}
作为一个过于简单的例子,您可以想象方括号给出了所请求的元素,即它们左边的元素,所以这是一个有点极端的例子:

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5}

    b := a[1:5]
    fmt.Printf("b: %v, a[1:5]               : %v\n",
        b, a[1:5])

    c := b[1:4]
    fmt.Printf("c: %v  , a[1:5][1:4]          : %v\n",
        c, a[1:5][1:4])

    d := c[1:3]
    fmt.Printf("d: %v    , a[1:5][1:4][1:3]     : %v\n",
        d, a[1:5][1:4][1:3])

    e := d[1:2]
    fmt.Printf("e: %v      , a[1:5][1:4][1:3][1:2]: %v\n",
        e, a[1:5][1:4][1:3][1:2])
}
哪些产出:

a[1:3]: [2 3]
b[1:3]: [3 4]
b: [2 3 4 5], a[1:5]               : [2 3 4 5]
c: [3 4 5]  , a[1:5][1:4]          : [3 4 5]
d: [4 5]    , a[1:5][1:4][1:3]     : [4 5]
e: [5]      , a[1:5][1:4][1:3][1:2]: [5]
以下是您的数据:

var m = [][]int{
    []int{0, 1, 2, 3},
    []int{4, 5, 6, 7},
    []int{8, 9, 10, 11},
    []int{12, 13, 14, 15},
}
首先你问什么是内在的:=m[1:3][1:3]

好的,一次取一个,m[1:3]是当你抓取元素1到3(不包括3)时得到的子切片。这就是元素1和2。元素0是[]int{0,1,2,3},元素1是[]int{4,5,6,7},元素2是[]int{8,9,10,11}

所以m[1:3]是

[][]int{
    []int{4, 5, 6, 7},
    []int{8, 9, 10, 11},
}
现在,为了得到m[1:3][1:3],我们在这个结果上重复同样的事情。 然而,这一次,只有两个要素。我们再次需要元素1和2。我们跳过元素0,它是[]int{4,5,6,7}。元素1是[]int{8,9,10,11}。没有元素2。然而,m[1:3]的结果是一个子切片,底层切片有一个额外的元素。 因此,通过扩展这个子片,我们可以再次得到那个元素,那就是hiddent元素2,它是[]int{12,13,14,15}。 所以m[1:3][1:3]是

[][]int{
    []int{8, 9, 10, 11},
    [[]int{12, 13, 14, 15},
}
最后,您想知道为什么func innerMatrix的工作方式不同?它首先产生m[1:3],这是

[][]int{
    []int{4, 5, 6, 7},
    []int{8, 9, 10, 11},
}
那么代码就不会像m[1:3][1:3]是两个连续的子片那样获取另一个子片。取而代之的是,获取切片中的每个元素并从每个元素中获取子切片。第一次从[]int{4,5,6,7}获取子切片[1:3]。结果是

[]int{5, 6}
第二次对第二个元素[]int{8,9,10,11}执行相同的操作,这是

[]int{9, 10} 
最后,每次通过将结果附加到结果片,因此将[]int{5,6}附加到[],以给出[][{int{5,6},然后将[]int{9,10}附加到给出

[][]{int{5, 6}, []int{9, 10} }