Go에서 변수의 가시성 규칙(스코핑)은 블록({})에 의해 엄격하게 정의되며, 변수 이름은 중첩된 영역에서 가려질 수 있습니다(셰도잉). 특히 중첩 함수, 익명 함수, 반복문 및 서로 다른 수준에서 동일한 이름의 변수를 선언할 때 많은 함정이 발생합니다.
Go는 코드의 가독성을 높이기 위해 가시성과 관련된 "마법 같은" 동작을 최소화했습니다. 그러나 구문 유연성과 짧은 형태 :=를 통한 변수 재선언은 인식 오류를 초래할 수 있습니다.
중첩 함수 또는 반복문 블록 내에서 최상위와 동일한 이름의 변수를 선언하면 외부 변수는 접근할 수 없게 됩니다(가려짐 — 셰도잉). 대부분의 경우 이것은 컴파일러에 의해 감지되지 않으며, 특히 클로저와 함께 작업할 때 오류의 원인이 될 수 있습니다. 또 다른 일반적인 오류는 if 블록이나 for-init에서 새로운 변수를 선언한 후 블록 외부에서 이를 사용하려고 할 때 발생합니다.
항상 가시성 수준을 주의 깊게 살펴봐야 합니다. 중첩 블록이나 익명 함수에서 동일한 변수 이름을 실제 필요 없이 사용하지 않도록 하고, 짧은 이름을 피하고 := 사용에 주의해야 합니다.
코드 예:
package main import "fmt" func main() { x := 1 { x := 2 // main()의 x를 가립니다. fmt.Println("Inner x:", x) } fmt.Println("Outer x:", x) for i := 0; i < 3; i++ { x := i // 각 반복에서 새로운 x가 생성됩니다. go func() { fmt.Println("Goroutine x:", x) }() } }
이 예에서 외부 변수 x는 변경되지 않으며, 블록 내에서 새로운 x가 생성됩니다. 두 번째 반복문에서 변수 x는 중첩 함수에서 캡처되므로 결과가 예상치 못한 것이 될 수 있습니다.
주요 특징:
:=는 항상 새 변수를 생성하며, 외부에 이미 존재하는 변수가 있어도 새로 생성됩니다.1. 중첩 블록에서 가려짐이 발생할 때 마지막으로 인쇄될 변수의 값은 무엇입니까?
외부 변수의 값이 됩니다. 내부 변수는 블록 내에서만 존재합니다.
2. if/for 블록 내에서 선언된 변수를 이 블록 밖에서 접근하려고 하면 어떻게 됩니까?
컴파일러가 오류를 발생시킵니다: 변수는 영역 밖에 있습니다.
if true { y := 5 } fmt.Println(y) // 오류
3. 반복문 내에서 변수를 사용하여 goroutine을 생성할 때 예상치 못한 값을 피하려면 어떻게 해야 합니까?
변수를 함수의 매개변수로 전달해야 합니다:
for i := 0; i < 3; i++ { go func(val int) { fmt.Println(val) }(i) }
:=가 이미 존재하는 변수를 변경할 것이라고 기대하는 것(새 변수를 생성합니다).반복문이 여러 goroutine을 병렬 처리하도록 초기화하지만, 그 안의 클로저에서 변수를 전달하지 않고 반복문 변수에 대한 접근을 사용합니다 — 모든 goroutine은 "마지막" 값으로 작업합니다.
장점:
단점:
반복문 변수를 클로저의 매개변수로 전달 — 각 goroutine은 자신의 값을 가집니다.
장점:
단점: