You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/spec-mini.md
+70Lines changed: 70 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1791,4 +1791,74 @@ TODO
1791
1791
1792
1792
### Package initialization
1793
1793
1794
+
Within a package, package-level variable initialization proceeds stepwise, with each step selecting the variable earliest in `declaration order` which has no dependencies on uninitialized variables.
1795
+
1796
+
More precisely, a package-level variable is considered ready for `initialization` if it is not yet initialized and either has no [initialization expression]() 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.
1797
+
1798
+
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.
1799
+
1800
+
Multiple variables on the left-hand side of a variable declaration initialized by single (multi-valued) expression on the right-hand side are initialized together: If any of the variables on the left-hand side is initialized, all those variables are initialized in the same step.
1801
+
1802
+
```go
1803
+
varx = a
1804
+
vara, b = f() // a and b are initialized together, before x is initialized
1805
+
```
1806
+
1807
+
For the purpose of package initialization, [blank]() variables are treated like any other variables in declarations.
1808
+
1809
+
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. 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.
1810
+
1811
+
Dependency analysis does not rely on the actual values of the variables, only on lexical `references` to them in the source, analyzed transitively. For instance, if a variable x's initialization expression refers to a function whose body refers to variable y then x depends on y. Specifically:
1812
+
1813
+
* A reference to a variable or function is an identifier denoting that variable or function.
1814
+
* A reference to a method m is a [method value]() or [method expression]() of the form `t.m`, where the (static) type of t is not an interface type, and the method `m` is in the method set of `t`. It is immaterial whether the resulting function value `t.m` is invoked.
1815
+
* A variable, function, or method x depends on a variable y if x's initialization expression or body (for functions and methods) contains a reference to y or to a function or method that depends on y.
1816
+
1817
+
For example, given the declarations
1818
+
1819
+
```go
1820
+
var (
1821
+
a = c + b // == 9
1822
+
b = f() // == 4
1823
+
c = f() // == 5
1824
+
d = 3// == 5 after initialization has finished
1825
+
)
1826
+
1827
+
funcf() int {
1828
+
d++
1829
+
return d
1830
+
}
1831
+
```
1832
+
1833
+
the initialization order is `d`, `b`, `c`, `a`. Note that the order of subexpressions in initialization expressions is irrelevant: `a = c + b` and `a = b + c` result in the same initialization order in this example.
1834
+
1835
+
Dependency analysis is performed per package; only references referring to variables, functions, and (non-interface) methods declared in the current package are considered. If other, hidden, data dependencies exists between variables, the initialization order between those variables is unspecified.
1836
+
1837
+
For instance, given the declarations
1838
+
1839
+
```go
1840
+
varx = I(T{}).ab() // x has an undetected, hidden dependency on a and b
1841
+
var_ = sideEffect() // unrelated to x, a, or b
1842
+
vara = b
1843
+
varb = 42
1844
+
1845
+
typeIinterface { ab() []int }
1846
+
typeTstruct{}
1847
+
func(T) ab() []int { return []int{a, b} }
1848
+
```
1849
+
1850
+
the variable `a` will be initialized after `b` but whether `x` is initialized before `b`, between `b` and `a`, or after `a`, and thus also the moment at which `sideEffect()` is called (before or after `x` is initialized) is not specified.
1851
+
1852
+
Variables may also be initialized using functions named init declared in the package block, with no arguments and no result parameters.
1853
+
1854
+
```go
1855
+
funcinit() { … }
1856
+
```
1857
+
1858
+
Multiple such functions may be defined per package, even within a single source file. In the package block, the `init` identifier can be used only to declare `init` functions, yet the identifier itself is not [declared](). Thus init functions cannot be referred to from anywhere in a program.
1859
+
1860
+
The entire package is initialized by assigning initial values to all its package-level variables followed by calling all `init` functions in the order they appear in the source, possibly in multiple files, as presented to the compiler.
0 commit comments