BTW, the rewritten version outputs

Init A
Init B
Init C
1   4   3

On my machine (go1.18 linux/amd64).
On Thursday, March 24, 2022 at 7:30:37 PM UTC+8 tapi...@gmail.com wrote:

> > 2. A < D < B < C - happens when f2.go is passed first to the compiler. 
> In this case, the *expected output *would be "1 2 1". However, the *actual 
> output* is "1 2 3".
>
> This is not true by my understanding of the spec.
> https://go.dev/ref/spec#Package_initialization
>
> If f2.go is passed first, then the order of uninitialized variables is D < 
> A < B < C.
> As D depends on A, so D is not initialized in the first initialization 
> cycle.
> In the first initialization cycle, A, B, and C and initialized as 3, 4, 
> and 3.
> In the second initialization cycle, D is initialized as 1 and A is changed 
> to 1.
> So the output should be 1 4 3.
>
> The same output is for the case if f1.go is passed first.
>
> On Thursday, March 24, 2022 at 5:24:09 AM UTC+8 Ian Lance Taylor wrote:
>
>> On Wed, Mar 23, 2022 at 2:01 PM Joao Carlos <joaoper...@gmail.com> 
>> wrote: 
>> > 
>> > I'm currently observing a behavior in the package initialization that 
>> looks incompatible with the Go language specification. 
>> > Let's consider the following two .go files which are in the same 
>> package 
>> > 
>> > f1.go 
>> > package main 
>> > 
>> > var A int = 3 
>> > var B int = A + 1 
>> > var C int = A 
>> > 
>> > f2.go 
>> > package main 
>> > 
>> > import "fmt" 
>> > 
>> > var D = f() 
>> > 
>> > func f() int { 
>> > A = 1 
>> > return 1 
>> > } 
>> > 
>> > func main() { 
>> > fmt.Println(A, " ", B, " ", C) 
>> > } 
>> > 
>> > According to the Go language specification, "package-level variable 
>> initialization proceeds stepwise, with each step selecting the variable 
>> earliest in declaration order which has no dependencies on uninitialized 
>> variables". 
>> > 
>> > As such, I would expect two possible orders in which the global 
>> variables can be initialized: 
>> > 1. A < B < C < D - happens when you compile the project by passing 
>> f1.go first to the compiler, followed by f2.go . In this case, the output 
>> is "1 4 3" 
>> > 2. A < D < B < C - happens when f2.go is passed first to the compiler. 
>> In this case, the expected output would be "1 2 1". However, the actual 
>> output is "1 2 3". 
>> > 
>> > Adding to this, I observed that if we rewrite f1.go to the following, 
>> the program now has the expected behavior when we pass f2.go first to the 
>> compiler. 
>> > 
>> > rewritten f1.go 
>> > package main 
>> > 
>> > import "fmt" 
>> > 
>> > var A int = initA() 
>> > var B int = initB() 
>> > var C int = initC() 
>> > 
>> > func initA() int { 
>> > fmt.Println("Init A") 
>> > return 3 
>> > } 
>> > 
>> > func initB() int { 
>> > fmt.Println("Init B") 
>> > return A + 1 
>> > } 
>> > 
>> > func initC() int { 
>> > fmt.Println("Init C") 
>> > return A 
>> > } 
>> > 
>> > Output 
>> > Init A 
>> > Init B 
>> > Init C 
>> > 1 2 1 
>> > 
>> > I observed this behavior in multiple versions of Go, including: 
>> > - go1.16.4 darwin/amd64 
>> > - go1.17.2 linux/amd64 
>> > - go1.18 linux/amd64 
>> > 
>> > Is this the expected behavior? Am I overlooking any details in the Go 
>> language specification or in the Go memory model? Or is this a bug in the 
>> compiler? 
>>
>> I think you're right: I think this is a bug. 
>>
>> Interestingly, I think the runtime package may rely on this bug. In 
>> the runtime package I see 
>>
>> var maxSearchAddr = maxOffAddr 
>> var maxOffAddr = offAddr{(((1 << heapAddrBits) - 1) + arenaBaseOffset) 
>> & uintptrMask} 
>>
>> and pageAlloc.Init, which is called by mheap.init which is called by 
>> mallocinit which is called by schedinit before package initializers 
>> are run. So the compiler is implementing an optimization to 
>> initialize maxSearchAddr before running package initialization 
>> routines, which I suppose is OK provided it that it can prove that the 
>> variable is never set by any function run during package 
>> initialization. 
>>
>> Want to open a bug report at https://go.dev/issue? Thanks. 
>>
>> Ian 
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/47e3c43d-65f6-4743-b9b9-60626c9142e0n%40googlegroups.com.

Reply via email to