mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
spec: specify variable initialization order explicitly
The existing spec rules on package initialization were contradictory: They specified that 1) dependent variables are initialized in dependency order, and 2) independent variables are initialized in declaration order. This 2nd rule cannot be satisfied in general. For instance, for var ( c = b + 2 a = 0 b = 1 ) because of its dependency on b, c must be initialized after b, leading to the partial order b, c. Because a is independent of b but is declared before b, we end up with the order: a, b, c. But a is also independent of c and is declared after c, so the order b, c, a should also be valid in contradiction to a, b, c. The new rules are given in form of an algorithm which outlines initialization order explicitly. gccgo and go/types already follow these rules. Fixes #8485. LGTM=iant, r, rsc R=r, rsc, iant, ken, gordon.klaus, adonovan CC=golang-codereviews https://golang.org/cl/142880043
This commit is contained in:
parent
dfddd802ac
commit
259f0ffade
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of September 25, 2014",
|
||||
"Subtitle": "Version of September 29, 2014",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
@ -5927,20 +5927,42 @@ var t T
|
|||
</pre>
|
||||
|
||||
<h3 id="Package_initialization">Package initialization</h3>
|
||||
|
||||
<p>
|
||||
Within a package, package-level variables are initialized according
|
||||
to their <i>dependencies</i>: if a variable <code>x</code> depends on
|
||||
a variable <code>y</code>, <code>x</code> will be initialized after
|
||||
<code>y</code>.
|
||||
Within a package, package-level variables are initialized in
|
||||
<i>declaration order</i> but after any of the variables
|
||||
they <i>depend</i> on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
More precisely, a package-level variable is considered <i>ready for
|
||||
initialization</i> if it is not yet initialized and either has
|
||||
no <a href="#Variable_declarations">initialization expression</a> or
|
||||
its initialization expression has no dependencies on uninitialized variables.
|
||||
Initialization proceeds by repeatedly initializing the next package-level
|
||||
variable that is earliest in declaration order and ready for initialization,
|
||||
until there are no variables ready for initialization.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If any variables are still uninitialized when this
|
||||
process ends, those variables are part of one or more initialization cycles,
|
||||
and the program is not valid.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The declaration order of variables declared in multiple files is determined
|
||||
by the order in which the files are presented to the compiler: Variables
|
||||
declared in the first file are declared before any of the variables declared
|
||||
in the second file, and so on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Dependency analysis does not rely on the actual values of the
|
||||
variables, only on lexical <i>references</i> to them in the source,
|
||||
analyzed transitively. For instance, a variable <code>x</code>'s
|
||||
<a href="#Variable_declarations">initialization expression</a>
|
||||
may refer to a function whose body refers to variable <code>y</code>;
|
||||
if so, <code>x</code> depends on <code>y</code>.
|
||||
analyzed transitively. For instance, if a variable <code>x</code>'s
|
||||
initialization expression refers to a function whose body refers to
|
||||
variable <code>y</code> then <code>x</code> depends on <code>y</code>.
|
||||
Specifically:
|
||||
</p>
|
||||
|
||||
|
@ -5973,11 +5995,6 @@ or to a function or method that depends on <code>y</code>.
|
|||
Dependency analysis is performed per package; only references referring
|
||||
to variables, functions, and methods declared in the current package
|
||||
are considered.
|
||||
It is an error if variable dependencies form a cycle
|
||||
(but dependency cycles containing no variables are permitted).
|
||||
If two variables are independent of each other,
|
||||
they are initialized in the order they are declared
|
||||
in the source, possibly in multiple files, as presented to the compiler.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -6000,8 +6017,6 @@ func f() int {
|
|||
|
||||
<p>
|
||||
the initialization order is <code>d</code>, <code>b</code>, <code>c</code>, <code>a</code>.
|
||||
Since <code>b</code> and <code>c</code> are independent of each other, they are
|
||||
initialized in declaration order (<code>b</code> before <code>c</code>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -6044,6 +6059,12 @@ the <code>init</code> functions: it will not invoke the next one
|
|||
until the previous one has returned.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To ensure reproducible initialization behavior, build systems are encouraged
|
||||
to present multiple files belonging to the same package in lexical file name
|
||||
order to a compiler.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="Program_execution">Program execution</h3>
|
||||
<p>
|
||||
|
|
Loading…
Reference in a new issue