mirror of https://github.com/golang/go.git
spec: clarify variable declaration type rules
Not a language change. Several inaccuracies were fixed: 1) A variable declaration may declare more than just one variable. 2) Variable initialization follows the rules of assignments, including n:1 assignments. The existing wording implied a 1:1 or n:n rule and generally was somewhat unspecific. 3) The rules for variable declarations with no types and untyped initialization expressions had minor holes (issue 8088). 4) Clarified the special cases of assignments of untyped values (we don't just have untyped constants, but also untyped bools, e.g. from comparisons). The new wording is more direct. To that end, introduced the notion of an untyped constant's "default type" so that the same concept doesn't have to be repeatedly introduced. Fixes #8088. LGTM=iant, r, rsc R=r, rsc, iant, ken CC=golang-codereviews https://golang.org/cl/142320043
This commit is contained in:
parent
c017a4e118
commit
47094dcf09
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of September 29, 2014",
|
"Subtitle": "Version of September 30, 2014",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -577,7 +577,7 @@ Numeric constants represent values of arbitrary precision and do not overflow.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Constants may be <a href="#Types">typed</a> or untyped.
|
Constants may be <a href="#Types">typed</a> or <i>untyped</i>.
|
||||||
Literal constants, <code>true</code>, <code>false</code>, <code>iota</code>,
|
Literal constants, <code>true</code>, <code>false</code>, <code>iota</code>,
|
||||||
and certain <a href="#Constant_expressions">constant expressions</a>
|
and certain <a href="#Constant_expressions">constant expressions</a>
|
||||||
containing only untyped constant operands are untyped.
|
containing only untyped constant operands are untyped.
|
||||||
|
|
@ -597,6 +597,17 @@ can be given the types <code>float32</code>, <code>float64</code>, or <code>uint
|
||||||
not <code>int32</code> or <code>string</code>.
|
not <code>int32</code> or <code>string</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
An untyped constant has a <i>default type</i> which is the type to which the
|
||||||
|
constant is implicitly converted in contexts where a typed value is required,
|
||||||
|
for instance, in a <a href="#Short_variable_declarations">short variable declaration</a>
|
||||||
|
such as <code>i := 0</code> where there is no explicit type.
|
||||||
|
The default type of an untyped constant is <code>bool</code>, <code>rune</code>,
|
||||||
|
<code>int</code>, <code>float64</code>, <code>complex128</code> or <code>string</code>
|
||||||
|
respectively, depending on whether it is a boolean, rune, integer, floating-point,
|
||||||
|
complex, or string constant.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
There are no constants denoting the IEEE-754 infinity and not-a-number values,
|
There are no constants denoting the IEEE-754 infinity and not-a-number values,
|
||||||
but the <a href="/pkg/math/"><code>math</code> package</a>'s
|
but the <a href="/pkg/math/"><code>math</code> package</a>'s
|
||||||
|
|
@ -1882,9 +1893,10 @@ func (tz TimeZone) String() string {
|
||||||
<h3 id="Variable_declarations">Variable declarations</h3>
|
<h3 id="Variable_declarations">Variable declarations</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A variable declaration creates a variable, binds an identifier to it and
|
A variable declaration creates one or more variables, binds corresponding
|
||||||
gives it a type and optionally an initial value.
|
identifiers to them, and gives each a type and an initial value.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
|
VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
|
||||||
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
|
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
|
||||||
|
|
@ -1905,22 +1917,27 @@ var _, found = entries[name] // map lookup; only interested in "found"
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If a list of expressions is given, the variables are initialized
|
If a list of expressions is given, the variables are initialized
|
||||||
by <a href="#Assignments">assigning</a> the expressions to the variables
|
with the expressions following the rules for <a href="#Assignments">assignments</a>.
|
||||||
in order; all expressions must be consumed and all variables initialized from them.
|
|
||||||
Otherwise, each variable is initialized to its <a href="#The_zero_value">zero value</a>.
|
Otherwise, each variable is initialized to its <a href="#The_zero_value">zero value</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If the type is present, each variable is given that type.
|
If a type is present, each variable is given that type.
|
||||||
Otherwise, the types are deduced from the assignment
|
Otherwise, each variable is given the type of the corresponding
|
||||||
of the expression list.
|
initialization value in the assignment.
|
||||||
|
If that value is an untyped constant, it is first
|
||||||
|
<a href="#Conversions">converted</a> to its <a href="#Constants">default type</a>;
|
||||||
|
if it is an untyped boolean value, it is first converted to type <code>bool</code>.
|
||||||
|
The predeclared value <code>nil</code> cannot be used to initialize a variable
|
||||||
|
with no explicit type.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<pre>
|
||||||
If the type is absent and the corresponding expression evaluates to an
|
var d = math.Sin(0.5) // d is int64
|
||||||
untyped <a href="#Constants">constant</a>, the type of the declared variable
|
var i = 42 // i is int
|
||||||
is as described in §<a href="#Assignments">Assignments</a>.
|
var t, ok = x.(T) // t is T, ok is bool
|
||||||
</p>
|
var n = nil // illegal
|
||||||
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Implementation restriction: A compiler may make it illegal to declare a variable
|
Implementation restriction: A compiler may make it illegal to declare a variable
|
||||||
|
|
@ -4318,7 +4335,7 @@ a[i] = 23
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code>
|
An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code>
|
||||||
<code>y</code> where <i>op</i> is a binary arithmetic operation equivalent
|
<code>y</code> where <i>op</i> is a binary arithmetic operation is equivalent
|
||||||
to <code>x</code> <code>=</code> <code>x</code> <i>op</i>
|
to <code>x</code> <code>=</code> <code>x</code> <i>op</i>
|
||||||
<code>y</code> but evaluates <code>x</code>
|
<code>y</code> but evaluates <code>x</code>
|
||||||
only once. The <i>op</i><code>=</code> construct is a single token.
|
only once. The <i>op</i><code>=</code> construct is a single token.
|
||||||
|
|
@ -4336,8 +4353,8 @@ i &^= 1<<n
|
||||||
A tuple assignment assigns the individual elements of a multi-valued
|
A tuple assignment assigns the individual elements of a multi-valued
|
||||||
operation to a list of variables. There are two forms. In the
|
operation to a list of variables. There are two forms. In the
|
||||||
first, the right hand operand is a single multi-valued expression
|
first, the right hand operand is a single multi-valued expression
|
||||||
such as a function evaluation or <a href="#Channel_types">channel</a> or
|
such as a function call, a <a href="#Channel_types">channel</a> or
|
||||||
<a href="#Map_types">map</a> operation or a <a href="#Type_assertions">type assertion</a>.
|
<a href="#Map_types">map</a> operation, or a <a href="#Type_assertions">type assertion</a>.
|
||||||
The number of operands on the left
|
The number of operands on the left
|
||||||
hand side must match the number of values. For instance, if
|
hand side must match the number of values. For instance, if
|
||||||
<code>f</code> is a function returning two values,
|
<code>f</code> is a function returning two values,
|
||||||
|
|
@ -4411,23 +4428,21 @@ to the type of the operand to which it is assigned, with the following special c
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li><p>
|
<li>
|
||||||
If an untyped <a href="#Constants">constant</a>
|
Any typed value may be assigned to the blank identifier.
|
||||||
is assigned to a variable of interface type or the blank identifier,
|
</li>
|
||||||
the constant is first <a href="#Conversions">converted</a> to type
|
|
||||||
<code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
|
|
||||||
<code>complex128</code> or <code>string</code> respectively, depending on
|
|
||||||
whether the value is a boolean, rune, integer, floating-point, complex, or
|
|
||||||
string constant.
|
|
||||||
</p></li>
|
|
||||||
|
|
||||||
<li><p>
|
<li>
|
||||||
<!-- Note that the result of a comparison is an untyped bool that may not be constant. -->
|
If an untyped constant
|
||||||
If a left-hand side is the blank identifier, any typed or non-constant
|
is assigned to a variable of interface type or the blank identifier,
|
||||||
value except for the predeclared identifier
|
the constant is first <a href="#Conversions">converted</a> to its
|
||||||
<a href="#Predeclared_identifiers"><code>nil</code></a>
|
<a href="#Constants">default type</a>.
|
||||||
may be assigned to it.
|
</li>
|
||||||
</p></li>
|
|
||||||
|
<li>
|
||||||
|
If an untyped boolean value is assigned to a variable of interface type or
|
||||||
|
the blank identifier, it is first converted to type <code>bool</code>.
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h3 id="If_statements">If statements</h3>
|
<h3 id="If_statements">If statements</h3>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue