Go语言通过无缓冲通道进行同时赋值:它是如何工作的?

huangapple go评论88阅读模式
英文:

Go language simultaneous assignment through un-buffered channel: how does it work?

问题

我正在学习Go,并在go.dev/tour/concurrency/2上看到了这个程序。

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y)
}

我记得在Python中,a, b = b, a 的执行流程应该是这样的:

  1. 创建一个临时元组 (b, a)。
  2. 使用循环将 (b, a) 中的每个值分配给 (a, b) 中的变量。

这种方法似乎不适用于Go中的这种情况。那么在 a, b = b, a 这个语句中实际发生了什么呢?

英文:

I'm learning Go and saw this program at go.dev/tour/concurrency/2

package main

import &quot;fmt&quot;

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c &lt;- sum // send sum to c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := &lt;-c, &lt;-c // receive from c

	fmt.Println(x, y, x+y)
}

I recall that in python the execution flow of a, b = b, a should be like:

> 1. Create a temporary tuple of (b, a)

> 2. Assign each value in (b, a) to variables in (a, b) with a loop

The method doesn't seem to apply to this occasion in GO. So what actually happens in that a, b = b, a sentence?

答案1

得分: 2

a, b = b, a 是一个赋值语句,更具体地说是一个元组赋值。

规范: 赋值语句中有详细说明:

元组赋值将多值操作的各个元素分配给变量列表。

[...]
赋值分为两个阶段。首先,左侧的索引表达式和指针间接引用(包括选择器中的隐式指针间接引用)以及右侧的表达式都按照通常的顺序进行求值。其次,按从左到右的顺序执行赋值。

a, b = b, a  // 交换 a 和 b

因此,首先读取 ba 的(当前)值,然后将它们分配给 ab,从而有效地交换它们的值。

这个例子:

x, y := <-c, <-c

是一个短变量声明,它等价于一个常规的变量声明,带有初始化表达式但没有类型:

var x, y = <-c, <-c

这将从 c 接收两次,并将接收到的值分配给 xy

英文:

a, b = b, a is an assignment, more specifically a tuple assignment.

It is detailed in the Spec: Assignments:

> A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables.
>
> [...]
> The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
>
> a, b = b, a // exchange a and b

So first the (current) values of b and a are read, then they are assigned to a, b, effectively swapping their values.

This:

x, y := &lt;-c, &lt;-c

Is a short variable declaration, it is equivalent to a regular variable declaration with initializer expressions but no types:

var x, y = &lt;-c, &lt;-c

This will receive from c, twice, and assign the received values to x and y.

huangapple
  • 本文由 发表于 2021年11月24日 19:45:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/70095523.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定