Let’s start right away with two simple Go programs:

program#1

package main import "fmt" var (

a int = b + 1

b int = 1

) func main() {

fmt.Println(a)

fmt.Println(b)

}

program#2

package main import "fmt" func main() {

var (

a int = b + 1

b int = 1

)

fmt.Println(a)

fmt.Println(b)

}

It would be a rather weak material for a story if both snippets would produce the same result. Fortunately they don’t:

program#1

2

1

program#2

This one doesn’t even build and produces only compile-time error “undefined: b” at line 7.

What exactly underpins this difference? “Normally” initialization expressions in variable declarations are evaluated as you might expect so left-to-right and top-to-bottom:

func f() int { fmt.Println("f"); return 1 }

func g() int { fmt.Println("g"); return 2 }

func h() int { fmt.Println("h"); return 3 } func main() {

var (

a int = f()

b int = g()

c int = h()

)

fmt.Println(a, b, c)

}

outputs:

f

g

h

1 2 3

Aforementioned “normally” means that it’s done inside function. When it goes to top level declarations (at package level) as in program#1 situation is more interesting as initialization dependencies come into play:

package main import "fmt" var (

a = c — 2

b = 2

c = f()

) func f() int {

fmt.Printf("inside f and b = %d

", b)

return b + 1

} func main() {

fmt.Println(a)

fmt.Println(b)

fmt.Println(c)

}

Declaration order is as follows:

b is first since it doesn’t have any dependencies on uninitialized variables,

c is next as after first initialization cycle b is already declared (which is required by f function),

a is handled in 3rd cycle when c is ready

Program’s output for formalities:

inside f and b = 2

1

2

3

Each initialization cycle picks first (in declaration order) variable which is ready . The whole procedure last till all variables are done or compiler finds a loop like in:

package main import "fmt" var (

a = b

b = c

c = f()

) func f() int {

return a

} func main() {

fmt.Println(a, b, c)

}

which produces compilation-time error “initialization loop”.

Initialization dependency machinery work at package level:

sandbox.go

package main import "fmt" var (

a = c — 2

b = 2

) func main() {

fmt.Println(a)

fmt.Println(b)

fmt.Println(c)

}

utils.go

package main var c = f() func f() int {

return b + 1

}

builds glibly and outputs:

1

2

3

If you liked what is above please boost work on future stories by following me.