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

时间:2016-10-16 18:18:28

标签: go variable-assignment slice scanline

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

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:]
    }
}

我找到了change request这里添加了文档,而更改作者有这个正常/易于理解的代码:

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

但是,有以下评论:

  

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

     

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

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

2 个答案:

答案 0 :(得分:5)

此:

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

是元组assignment。它会为picture[i]指定一个值,为pixels指定一个值。按顺序分配的值为pixels[:XSize]pixels[XSize:]

  

转让分两个阶段进行。首先,左侧index expressionspointer indirections的操作数(包括selectors中的隐式指针间接)和右侧的表达式都是evaluated in the usual order。其次,分配按从左到右的顺序进行。

这里发生的是当循环开始时(i = 0),picture(第一行)的第一个元素被赋值为一个切片值,即第一个XSize个元素。 pixelspixels切片已被重置,因此其第一个元素将是XSize th 元素+1。

因此,在下一次迭代中,picture[i]将成为picture(第2行)中的第2个元素,同样,来自XSize的第一个pixels元素将是设置为切片。但是因为在上一次迭代中我们重新pixels,所以在每次迭代中它的第一个XSize元素将是后续行。

答案 1 :(得分:2)

这个元组赋值示例可以重写为:

for i := range picture {
    picture[i]= pixels[:XSize]
    pixels = pixels[XSize:]
}

现在更容易看到图片像素的第一个 XSize 项目。

在每个循环中像素 被修改并删除其第一个 XSize 项目。