Go에서 포인터 수신기를 사용하는 메소드는 작동하는 변수의 원래 값을 유지하는 것으로 알려져 있습니다. 에. 그러나 메소드가 포인터 인수를 예상하고 포인터가 아닌 값을 전달하는 경우 명백한 모순이 있는 것 같습니다.
Go 둘러보기의 연습 51에 대한 아래 스니펫을 고려하세요.
func (v *Vertex) Scale(f float64) { v.X *= f v.Y *= f } func main() { v := &Vertex{3, 4} v.Scale(2) fmt.Println(v) // Output: &{6 8} }
설명에 따르면 Scale 메서드는 Vertex 대신 Vertex(*Vertex)에 대한 포인터를 받기 때문에 v를 수정해서는 안 됩니다.
그러나 기본에서 v := &Vertex{3, 4} 행을 v := Vertex{3, 4}로 변경하면 출력이 &{6 8}에서 {6 8로 변경됩니다. } (누락된 &에 주목하세요). 이는 포인터가 아닌 값으로 전달되었음에도 불구하고 v가 수정되었음을 나타냅니다.
핵심은 Go의 강력한 형식 특성과 컴파일러 최적화에 있습니다. Scale 메서드가 포인터 수신기를 기대하더라도 Go가 암시적으로 포인터로 변환하기 때문에 포인터가 아닌 값도 허용할 수 있습니다.
구체적으로 컴파일러는 다음 코드를 다시 작성합니다.
v := Vertex{3, 4} v.Scale(2)
to:
(&v).Scale(2)
이는 메소드가 실제로 v에 대한 포인터를 사용하여 호출된다는 의미이며, 이를 통해 원본을 수정할 수 있습니다. value.
다음 Go 관련 규칙은 이 동작을 설명합니다.
x의 메소드 세트(유형)에 m이 포함되고 인수 목록이 다음과 같은 경우 x.m() 메소드 호출이 유효합니다. m의 매개변수 목록에 할당됩니다. x가 주소 지정 가능하고 &x의 메소드 세트에 m이 포함된 경우 x.m()은 (&x).m()의 약어입니다.
요약하자면, 포인터 수신기가 있는 메소드는 컴파일러가 자동으로 변환하기 때문에 포인터가 아닌 변수를 계속 수정할 수 있습니다. 메소드 유형 안전성을 유지하기 위해 포인터에 연결합니다.
위 내용은 포인터 수신기를 사용하는 Go 메서드가 포인터가 아닌 인수를 수정하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!