Execution order for GoLang Struct Initializer

Issue

Was wondering if execution order for struct initialization is guaranteed in GoLang.

Does the following code always produce

obj.a == 1 and obj.b == 2 or is it unspecified behavior?

num := 0

nextNumber := func() int {
    num += 1
    return num
}

type TwoNumbers struct {
    a int
    b int
}

obj := TwoNumbers{
    a: nextNumber(),
    b: nextNumber(),
}

Solution

The evaluation order of the function calls is specified.

The code TwoNumbers{a: nextNumber(), b: nextNumber()} is a composite literal expression. The calls to nextNumber() are operands in the expression.

The specification says this about expressions in general:

… when evaluating the operands of an expression, assignment, or return statement, all function calls, method calls, and communication operations are evaluated in lexical left-to-right order.

The function call for field a is evaluated before the function call for field b because the function call for field a is to the left of the function call for field b.

The evaluation order is specified for function calls, method calls and communication operations only. The compiler can reorder the evaluation of other operands. In the following example, the expression for field a lexically to the left of the expression for field b, but b is evaluated first (in the current compiler).

type Numbers struct{ a, b, c int }
nums := Numbers{a: num, b: nextNumber(), c: nextNumber()}
fmt.Println(nums) // prints {2 1 2}

Run it on the playground

Answered By – Bayta Darell

Answer Checked By – Willingham (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.