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
Gordon Klaus (gordon.klaus@gmail.com) made a (in my mind) intriguing suggestion: He
proposes that initialization order should not be further specified beyond the existing
dependencies (and thus not depend on declaration order).
I would add to this that init() functions, too, should be invoked in unspecified order.
I very much like this idea for several reasons:
1) At the package-level, excluding variable initialization, declaration order is
irrelevant for the meaning of a program (note that iota is an explicit constant).
2) Across files of a package, the initialization order of independent variables depends
on the order in which the files are presented to the compiler. In practice, a programmer
doesn't have control over that order when using go build. It may be in filename order,
but it could be random (the files might be stored in a set). Thus, this is a situation
where the semantics of a package is not expressed in the source per se, but in how the
source code is handled by tools. This seems a bad idea.
3) The two compilers (currently, 9/12/2014) disagree in some cases about the correct
initialization order.
4) It would simplify the spec.
5) Where initialization order matters, a specific initialization function is the
preferred way of expressing that dependency.
6) Reordering code may subtly brake implicit ordering dependencies.
In order for such an approach to work well (and expose errors), an implementation should
enforce a different initialization order (while respecting dependencies) for each run,
like we have enforced different map iteration orders for each map iteration.
Here's a possible implementation:
1) Package-level variables that have no initialization expression, or have an
initialization expression that is independent on any other variable and has no
observable side-effects (incl. panics), are initialized in whatever order is easiest and
most efficient to generate code for, if code is even necessary.
2) For each of the remaining (usually small number of) variables x, allocate a
zero-initialized boolean flag bx and generate an accessor function fx as follows:
func fx() typeof(x) {
if !bx {
x = // init expression of x
bx = true
}
return x
}
3) In all init expressions, replace any reference to variables with calls to the
corresponding accessor functions, if any.
4) Add all the functions fx together with all init functions to a map.
5) Iterate through the map (in random order) and invoke each function.
That is, we solve the dependency problem at run-time for each package, and each time it
is as if the variables were declared in a different order.
The extra code would be fairly small given the small number of variables that are
initialized with dependencies or side-effects. The necessary program transformations are
straight-forward in a compiler.
The text was updated successfully, but these errors were encountered:
An old issue and not until Go 2 anyway, but I think it would be a mistake to relax these rules. Much like leaving map iteration order unspecified led to implementation-dependent code that only worked with one map iteration order, relaxing the init order here will lead to the same kind of code that only works with certain Go implementations. If there's any wiggle room left, I'd argue we should make things completely specified, not move in the other direction.
rsc
changed the title
spec: do not specify initialization order of package-level variables w/o dependencies
proposal: spec: do not specify initialization order of package-level variables w/o dependencies
Jun 17, 2017
Over the last few years we decided for making the spec more deterministic, not less so (with the notable exception of map iteration order). Proposal withdrawn.
The text was updated successfully, but these errors were encountered: