원문 링크 https://codewithyury.com/golang-pass-by-pointer-vs-pass-by-value/
Go는 매개변수 전달시 포인터(참조 전달이라고도 불리는)와 값 둘 다 지원합니다. 이 포스트에선 선택에 영향을 주는 특정 상황들에 유의해서 두가지 접근을 비교해 볼 것 입니다.
포인터로 전달 vs 값으로 전달
엄밀히 말해 Go에서 매개변수를 전달하는 방법은 값으로 전달 하나밖에 없습니다. 변수가 매개변수로 전달될 때 마다 변수의 사본이 생성되고 호출한 함수 혹은 메소드로 전달됩니다. 사본은 다른 메모리 주소에 할당됩니다.
값으로 전달
|
|
위 코드의 출력 값:
|
|
changeName 함수가 firstName의 값을 “Bob” 으로 바꿨는데도 main 함수의 person 변수 값에는 아무런 영향도 미치지 않았습니다. 이건 changeName 함수가 person 변수 원본이 아닌 사본을 수정했기 때문입니다.
포인터로 전달
|
|
위 코드의 출력 값:
|
|
이번엔 main 함수의 person 변수값이 changeName 함수 내에서 수정되었습니다. 이건 &person과 p 라는 별개의 포인터가 동일한 메모리 주소에 저장된 동일한 구조체를 가리키고 있기 때문입니다.
미리 결정된 경우
때로는 사용 방식에 따라 전달 방식이 이미 결정되어 있는 경우가 있습니다. 가장 흔한 경우를 살펴봅시다.
변수가 수정되어서는 안 되는 경우
변수가 수정되지 않게 하기 위해선 값으로 전달하는 것 말고는 선택의 여지가 없습니다. 반대로 변수가 수정되어야 한다면 포인터로 전달 되어야만 합니다.
변수가 큰 구조체인 경우
변수가 큰 구조체이고, 성능 이슈가 있다면 메모리의 거대한 구조체 전체를 복사하는 비싼 연산을 막기 위해 변수를 포인터로 전달하는 것도 고려해 볼 만 합니다.
변수가 map 이나 slice 인 경우
Go 에서 map과 slice는 참조타입이기 때문에 값으로 전달해야합니다.
값으로 전달하는것이 대체로 저렴합니다.
Go는 C랑 비슷해 보이지만, 컴파일러는 다르게 작동합니다. 그리고 C에서의 유추가 Go에서 통하지 않을 수 있습니다. Go에서 값으로 전달하는 것은 포인터로 전달하는 것보다 훨씬 저렴할 수 있습니다. 이는 Go가 변수를 함수 스택(힙보다 훨씬 저렴한)에 안전하게 저장 할 수 있는지 확인하기 위해 이스케이프 분석을 사용하기 때문입니다. 값으로 전달할 경우 Go의 이스케이프 분석이 간단해지고 변수가 스택에 할당될 확률이 올라갑니다.
결론
때로 사용 방식에 따라 변수의 전달 방법이 미리 결정되어 있는 경우도 있지만, 그게 아니라면 변수를 값으로 전달하는 것이 좋습니다. 또한 자신과 동료들이 혼동하지 않도록 전달 방식을 선택하는 규칙을 단일화 하는 것이 중요합니다.