mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
go spec: clarifications for range clause
R=iant, r, rsc, rog CC=golang-dev https://golang.org/cl/2226047
This commit is contained in:
parent
2ccbf83b32
commit
5474e166bc
1 changed files with 66 additions and 49 deletions
115
doc/go_spec.html
115
doc/go_spec.html
|
@ -1,5 +1,5 @@
|
|||
<!-- title The Go Programming Language Specification -->
|
||||
<!-- subtitle Version of Sep 27, 2010 -->
|
||||
<!-- subtitle Version of Sep 28, 2010 -->
|
||||
|
||||
<!--
|
||||
TODO
|
||||
|
@ -14,7 +14,6 @@ TODO
|
|||
[ ] should string(1<<s) and float(1<<s) be valid?
|
||||
[ ] should probably write something about evaluation order of statements even
|
||||
though obvious
|
||||
[ ] specify iteration direction for range clause
|
||||
[ ] review language on implicit dereferencing
|
||||
[ ] clarify what it means for two functions to be "the same" when comparing them
|
||||
-->
|
||||
|
@ -3572,8 +3571,8 @@ f(x+y)
|
|||
<p>
|
||||
The "++" and "--" statements increment or decrement their operands
|
||||
by the untyped <a href="#Constants">constant</a> <code>1</code>.
|
||||
As with an assignment, the operand must be a variable, pointer indirection,
|
||||
field selector or index expression.
|
||||
As with an assignment, the operand must be <a href="#Address_operators">addressable</a>
|
||||
or a map index expression.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -3591,6 +3590,7 @@ x++ x += 1
|
|||
x-- x -= 1
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Assignments">Assignments</h3>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -3949,59 +3949,81 @@ for { S() } is the same as for true { S() }
|
|||
<p>
|
||||
A "for" statement with a "range" clause
|
||||
iterates through all entries of an array, slice, string or map,
|
||||
or values received on a channel.
|
||||
For each entry it first assigns the current index or key to an iteration
|
||||
variable - or the current (index, element) or (key, value) pair to a pair
|
||||
of iteration variables - and then executes the block.
|
||||
or values received on a channel. For each entry it assigns <i>iteration values</i>
|
||||
to corresponding <i>iteration variables</i> and then executes the block.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
RangeClause = ExpressionList ( "=" | ":=" ) "range" Expression .
|
||||
RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "range" Expression .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The type of the right-hand expression in the "range" clause must be an
|
||||
array, slice, string or map, or a pointer to an array;
|
||||
or it may be a channel.
|
||||
Except for channels,
|
||||
the identifier list must contain one or two expressions
|
||||
(as in assignments, these must be a
|
||||
variable, pointer indirection, field selector, or index expression)
|
||||
denoting the
|
||||
iteration variables. On each iteration,
|
||||
the first variable is set to the string, array or slice index or
|
||||
map key, and the second variable, if present, is set to the corresponding
|
||||
string or array element or map value.
|
||||
The types of the array or slice index (always <code>int</code>)
|
||||
and element, or of the map key and value respectively,
|
||||
must be <a href="#Assignability">assignable</a> to
|
||||
the type of the iteration variables. The expression on the right hand
|
||||
side is evaluated once before beginning the loop. At each iteration
|
||||
of the loop, the values produced by the range clause are assigned to
|
||||
the left hand side as in an <a href="#Assignments">assignment
|
||||
statement</a>. Function calls on the left hand side will be evaluated
|
||||
exactly once per iteration.
|
||||
</p>
|
||||
The expression on the right in the "range" clause is called the <i>range expression</i>,
|
||||
which may be an array, pointer to an array, slice, string, map, or channel.
|
||||
As with an assignment, the operands on the left must be
|
||||
<a href="#Address_operators">addressable</a> or map index expressions; they
|
||||
denote the iteration variables. If the range expression is a channel, only
|
||||
one iteration variable is permitted, otherwise there may be one or two.
|
||||
<p>
|
||||
For a value of a string type, the "range" clause iterates over the Unicode code points
|
||||
in the string. On successive iterations, the index variable will be the
|
||||
index of the first byte of successive UTF-8-encoded code points in the string, and
|
||||
the second variable, of type <code>int</code>, will be the value of
|
||||
|
||||
</p>
|
||||
The range expression is evaluated once before beginning the loop.
|
||||
Function calls on the left are evaluated once per iteration.
|
||||
For each iteration, iteration values are produced as follows:
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
Range expression 1st value 2nd value (if 2nd variable is present)
|
||||
|
||||
array or slice a [n]E, *[n]E, or []E index i int a[i] E
|
||||
string s string type index i int see below int
|
||||
map m map[K]V key k K m[k] V
|
||||
channel c chan E element e E
|
||||
</pre>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
For an array or slice value, the index iteration values are produced in
|
||||
increasing order, starting at element index 0.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
For a string value, the "range" clause iterates over the Unicode code points
|
||||
in the string starting at byte index 0. On successive iterations, the index value will be the
|
||||
index of the first byte of successive UTF-8-encoded code points in the string,
|
||||
and the second value, of type <code>int</code>, will be the value of
|
||||
the corresponding code point. If the iteration encounters an invalid
|
||||
UTF-8 sequence, the second variable will be <code>0xFFFD</code>,
|
||||
UTF-8 sequence, the second value will be <code>0xFFFD</code>,
|
||||
the Unicode replacement character, and the next iteration will advance
|
||||
a single byte in the string.
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The iteration order over maps is not specified.
|
||||
If map entries that have not yet been reached are deleted during iteration,
|
||||
the corresponding iteration values will not be produced. If map entries are
|
||||
inserted during iteration, the behavior is implementation-dependent, but the
|
||||
iteration values for each entry will be produced at most once.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
For channels, the iteration values produced are the successive values sent on
|
||||
the channel until the channel is closed; it does not produce the zero value sent
|
||||
before the channel is closed
|
||||
(§<a href="#Close_and_closed"><code>close</code> and <code>closed</code></a>).
|
||||
</li>
|
||||
</ol
|
||||
|
||||
<p>
|
||||
For channels, the identifier list must contain one identifier.
|
||||
The iteration receives values sent on the channel until the channel is closed;
|
||||
it does not process the zero value sent before the channel is closed.
|
||||
The iteration values are assigned to the respective
|
||||
iteration variables as in an <a href="#Assignments">assignment statement</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The iteration variables may be declared by the "range" clause (":="), in which
|
||||
case their scope ends at the end of the "for" statement (§<a href="#Declarations_and">Declarations and</a>
|
||||
scope rules). In this case their types are set to
|
||||
<code>int</code> and the array element type, or the map key and value types, respectively.
|
||||
The iteration variables may be declared by the "range" clause (<code>:=</code>).
|
||||
In this case their types are set to the types of the respective iteration values
|
||||
and their <a href="#Declarations_and_scope">scope</a> ends at the end of the "for"
|
||||
statement; they are re-used in each iteration.
|
||||
If the iteration variables are declared outside the "for" statement,
|
||||
after execution their values will be those of the last iteration.
|
||||
</p>
|
||||
|
@ -4026,11 +4048,6 @@ for key, val = range m {
|
|||
// val == map[key]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If map entries that have not yet been processed are deleted during iteration,
|
||||
they will not be processed. If map entries are inserted during iteration, the
|
||||
behavior is implementation-dependent, but each entry will be processed at most once.
|
||||
</p>
|
||||
|
||||
<h3 id="Go_statements">Go statements</h3>
|
||||
|
||||
|
|
Loading…
Reference in a new issue