这种"常见习语"究竟如何运作?

Jon*_*han 1 variable-assignment go slice scanline

查看golang的2D切片的文档,无法理解上一个示例中使用的语法:

func main() {
    XSize := 5
    YSize := 5

    // Allocate the top-level slice, the same as before.
    picture := make([][]uint8, YSize) // One row per unit of y.

    // Allocate one large slice to hold all the pixels.
    pixels := make([]uint8, XSize*YSize) // Has type []uint8 even though picture is [][]uint8.

    // Loop over the rows, slicing each row from the front of the remaining pixe ls slice.
    for i := range picture {
        picture[i], pixels = pixels[:XSize], pixels[XSize:]
    }
}
Run Code Online (Sandbox Code Playgroud)

我找到了更改请求,将其添加到文档中,并且更改作者有这个正常/易于理解的代码:

// Loop over the rows, slicing each row.
for i := range picture {
     picture[i] = pixels[i*XSize:(i+1)*XSize]
Run Code Online (Sandbox Code Playgroud)

但是,有以下评论:

精细.另一个常见的习惯是避免数学:

picture[i], pixels = pixels[:XSize], pixels[XSize:]

我的问题是上面如何实现与"避免数学"方法相同的方法?关于正在发生的事情的一些文档会很棒.

icz*_*cza 5

这个:

picture[i], pixels = pixels[:XSize], pixels[XSize:]
Run Code Online (Sandbox Code Playgroud)

是一个元组赋值.它为一个值picture[i]和一个值赋值pixels.按顺序分配的值是pixels[:XSize]pixels[XSize:].

转让分两个阶段进行.首先,左边的索引表达式指针间接(包括选择器中的隐式指针间接)的操作数和右边的表达式都按照通常的顺序进行评估.其次,分配按从左到右的顺序进行.

这里发生的是当循环开始(i = 0)时,picture(第一行)的第一个元素被赋予一个切片值作为第一个XSize元素pixels,并且pixels切片被重新复制,因此它的第一个元素将是第XSizeth个元素+1.

因此在下一次迭代picture[i]中将是picture(第二行)中的第二个元素,并且第一个XSize元素pixels将被设置为切片.但是因为在上一次迭代中我们重新进行了重复pixels,所以在每次迭代中它的第一个XSize元素将是后续行.