tuckersGo / mustHaveGo2

1 stars 1 forks source link

19.4.2 함수 리터럴 내부 상태 주의점 #2

Closed Park-Jongseok closed 1 week ago

Park-Jongseok commented 2 weeks ago

안녕하세요. Tucker의 Go 언어 프로그래밍 잘 보고 있습니다.

문제

19.4.2 함수 리터럴 내부 상태 주의점의 예시 ch19/ex19.6/ex19.6.goCaptureLoop()의 함수에서 예상되는 동작과 다른 결과가 나와 제보드립니다.

원인 조사

결론적으로, 이는 Go 1.22 부터 for문에서의 변수 캡처 방식이 변경되었기 때문으로 판단됩니다.

Go 1.22 Release Note에 따르면 다음과 같은 내용이 있습니다.

Previously, the variables declared by a “for” loop were created once and updated by each iteration. In Go 1.22, each iteration of the loop creates new variables, to avoid accidental sharing bugs. The transition support tooling described in the proposal continues to work in the same way it did in Go 1.21.

이 변경 사항으로 인해, 이전에는 동일한 변수를 참조해 3, 3, 3과 같은 결과가 나왔다면, 이제는 각 반복에서 새로운 변수가 캡쳐되어 0, 1, 2로 출력됩니다.

확인

이 변경 사항을 확인하기 위해 The Go Playground에서 각각의 Go 버전으로 테스트를 진행했습니다.

Go Version 1.21의 경우

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
    f := make([]func(), 3)
    fmt.Println("ValueLoop")
    for i := 0; i < 3; i++ {
        f[i] = func() {
            fmt.Println(i)
        }
    }
    for i := 0; i < 3; i++ {
        f[i]()
    }
}
-- go.mod --
module main

go 1.21

결과

ValueLoop
3
3
3

Program exited.

Go Version 1.22 이상의 경우

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
    f := make([]func(), 3)
    fmt.Println("ValueLoop")
    for i := 0; i < 3; i++ {
        f[i] = func() {
            fmt.Println(i)
        }
    }
    for i := 0; i < 3; i++ {
        f[i]()
    }
}

결과

ValueLoop
0
1
2

정오표 확인

정오표 - Tucker의 Go 언어 프로그래밍(2판)를 확인했으나, 해당 내용이 포함되지 않아 연락드립니다.

혹시 제가 잘못 이해한 부분이 있거나, 추가로 조정할 사항이 있다면 알려주시면 감사하겠습니다.

tuckersGo commented 1 week ago

네 그부분은 정확히 맞습니다. 다음번 인쇄때 개정될 예정입니다.

Park-Jongseok commented 1 week ago

답변 감사합니다. 정상적인 동작임을 확인했으므로 이 문제를 닫습니다.