프로그래밍백엔드 개발자

Go는 함수에 map과 slice를 전달할 때 메모리 작업을 어떻게 구현하며, 이는 어떤 위험을 초래할 수 있나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

Go에서 map 구조체는 항상 값으로 전달되지만, 이 값은 map 자체의 내부 구조체에 대한 포인터를 포함합니다(내부적으로는 해시 테이블). 따라서 함수를 통해 map을 전달하고 함수 내에서 내용을 변경하면(요소를 추가/삭제), 외부에서 변경 사항을 볼 수 있습니다. slice의 경우도 마찬가지로 동작합니다 — slice 구조체는 복사되지만 원본 배열 데이터는 복사되지 않습니다: slice는 배열에 대한 포인터, 길이 및 용량을 포함합니다. 함수 내에서 인덱스를 통해 값을 변경하면 원본 배열 역시 변경됩니다. 그러나 함수 내에서 새로운 slice를 할당하면(예: reslice) 원본 변수는 변경되지 않습니다.

func updateMap(m map[string]int) { m["key"] = 42 // 변경 사항이 외부에 보입니다! } func updateSlice(s []int) { s[0] = 99 // 원본 배열이 변경됩니다 }

함정 질문.

왜 map과 slice를 함수에 전달할 때 함수 내에서의 변경이 "원본"에 반영되나요?

답변: 포인터 구조체만 복사되고 실제 데이터는 공유되므로 — 어떠한 변경이든 동일한 메모리 블록에 영향을 미칩니다.

주제에 대한 세부 사항을 알지 못해 발생한 실제 오류의 예.


이야기

핀테크 프로젝트에서 다양한 서비스에 설정 구성을 위한 map을 전달했으며, 로컬 변경이 전체 map에 영향을 미치지 않을 것이라고 생각했습니다. 그 결과, 하나의 서비스가 값을 변경했고, 이는 예상치 못한 수정된 구성을 받은 다른 모듈에서 버그를 초래했습니다.


이야기

분석 마이크로서비스에서 독립적인 복사본을 얻을 수 있을 것으로 예상하고 slice를 전달했습니다. 하지만, 함수 내에서 인덱스의 값을 변경하여 원본 배열이 예상치 않게 변경되면서 보고서의 데이터 왜곡이 발생했습니다.


이야기

게임 서버에서 사용자 세션 저장을 위해 map을 사용하고 이 map을 여러 고루틴에 동시에 전달했습니다. 각 고루틴이 자신의 복사본에서 작업한다고 가정했지만, 실제로 데이터 경쟁이 발생하고 일부 세션이 손실되었습니다.