diff options
author | Robert Griesemer <gri@golang.org> | 2014-05-14 11:47:19 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2014-05-14 11:47:19 -0700 |
commit | 2aedffc91e7a8c706ed9c4ba0aab6ff239c9c086 (patch) | |
tree | c1c4ea38e512e52763b06b6bad196316c5d7e910 /doc | |
parent | ebde8b93e51ec0c068e507a5b7b74d845728fe4d (diff) | |
download | go-2aedffc91e7a8c706ed9c4ba0aab6ff239c9c086.tar.gz |
spec: more precise description of select statement
- use previously defined terms (with links) throughout
- specify evaluation order more precisely (in particular,
the evaluation time of rhs expressions in receive cases
was not specified)
- added extra example case
Not a language change.
Description matches observed behavior of code compiled
with gc and gccgo.
Fixes issue 7669.
LGTM=iant, r, rsc
R=r, rsc, iant, ken, josharian
CC=golang-codereviews
https://codereview.appspot.com/91230043
Diffstat (limited to 'doc')
-rw-r--r-- | doc/go_spec.html | 96 |
1 files changed, 63 insertions, 33 deletions
diff --git a/doc/go_spec.html b/doc/go_spec.html index 2f6fd2b97..8a7e8ec03 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ <!--{ "Title": "The Go Programming Language Specification", - "Subtitle": "Version of May 7, 2014", + "Subtitle": "Version of May 14, 2014", "Path": "/ref/spec" }--> @@ -1331,8 +1331,8 @@ make(chan int, 100) <p> The capacity, in number of elements, sets the size of the buffer in the channel. If the capacity is zero or absent, the channel is unbuffered and communication -succeeds only when both a sender and receiver are ready. Otherwise, the channel is -buffered and communication operations succeed without blocking if the buffer +succeeds only when both a sender and receiver are ready. Otherwise, the channel +is buffered and communication succeeds without blocking if the buffer is not full (sends) or not empty (receives). A <code>nil</code> channel is never ready for communication. </p> @@ -4879,8 +4879,12 @@ go func(ch chan<- bool) { for { sleep(10); ch <- true; }} (c) <h3 id="Select_statements">Select statements</h3> <p> -A "select" statement chooses which of a set of possible communications -will proceed. It looks similar to a "switch" statement but with the +A "select" statement chooses which of a set of possible +<a href="#Send_statements">send</a> or +<a href="#Receive_operator">receive</a> +operations will proceed. +It looks similar to a +<a href="#Switch_statements">"switch"</a> statement but with the cases all referring to communication operations. </p> @@ -4893,41 +4897,63 @@ RecvExpr = Expression . </pre> <p> -RecvExpr must be a <a href="#Receive_operator">receive operation</a>. -For all the cases in the "select" -statement, the channel expressions are evaluated in top-to-bottom order, along with -any expressions that appear on the right hand side of send statements. -A channel may be <code>nil</code>, -which is equivalent to that case not -being present in the select statement -except, if a send, its expression is still evaluated. -If any of the resulting operations can proceed, one of those is -chosen and the corresponding communication and statements are -evaluated. Otherwise, if there is a default case, that executes; -if there is no default case, the statement blocks until one of the communications can -complete. There can be at most one default case and it may appear anywhere in the -"select" statement. -If there are no cases with non-<code>nil</code> channels, -the statement blocks forever. -Even if the statement blocks, -the channel and send expressions are evaluated only once, -upon entering the select statement. +A case with a RecvStmt may assign the result of a RecvExpr to one or +two variables, which may be declared using a +<a href="#Short_variable_declarations">short variable declaration</a>. +The RecvExpr must be a (possibly parenthesized) receive operation. +There can be at most one default case and it may appear anywhere +in the list of cases. </p> + <p> -Since all the channels and send expressions are evaluated, any side -effects in that evaluation will occur for all the communications -in the "select" statement. +Execution of a "select" statement proceeds in several steps: </p> + +<ol> +<li> +For all the cases in the statement, the channel operands of receive operations +and the channel and right-hand-side expressions of send statements are +evaluated exactly once, in source order, upon entering the "select" statement. +The result is a set of channels to receive from or send to, +and the corresponding values to send. +Any side effects in that evaluation will occur irrespective of which (if any) +communication operation is selected to proceed. +Expressions on the left-hand side of a RecvStmt with a short variable declaration +or assignment are not yet evaluated. +</li> + +<li> +If one or more of the communications can proceed, +a single one that can proceed is chosen via a uniform pseudo-random selection. +Otherwise, if there is a default case, that case is chosen. +If there is no default case, the "select" statement blocks until +at least one of the communications can proceed. +</li> + +<li> +Unless the selected case is the default case, the respective communication +operation is executed. +</li> + +<li> +If the selected case is a RecvStmt with a short variable declaration or +an assignment, the left-hand side expressions are evaluated and the +received value (or values) are assigned. +</li> + +<li> +The statement list of the selected case is executed. +</li> +</ol> + <p> -If multiple cases can proceed, a uniform pseudo-random choice is made to decide -which single communication will execute. -<p> -The receive case may declare one or two new variables using a -<a href="#Short_variable_declarations">short variable declaration</a>. +Since communication on <code>nil</code> channels can never proceed, +a select with only <code>nil</code> channels and no default case blocks forever. </p> <pre> -var c, c1, c2, c3 chan int +var a []int +var c, c1, c2, c3, c4 chan int var i1, i2 int select { case i1 = <-c1: @@ -4940,6 +4966,10 @@ case i3, ok := (<-c3): // same as: i3, ok := <-c3 } else { print("c3 is closed\n") } +case a[f()] = <-c4: + // same as: + // case t := <-c4 + // a[f()] = t default: print("no communication\n") } |