값의 표현

값의 표현

Go에서 값이 실제로 어떻게 저장되고 공유되는지 궁금하시죠? 여기서 핵심은 이거예요. 어떤 타입은 값을 통째로 자기 안에 들고 있고, 어떤 타입은 그 뒤에 있는 데이터를 가리키는 참조만 들고 있어요. 이 차이를 이해하면, 왜 어느 한 값을 바꿨는데 다른 값까지 함께 변하는 일이 생기는지가 자연스럽게 보여요.

출처: Go Specification

본문

프리디클레어드 타입의 값들(아래에서 다룰 anyerror 인터페이스도 여기 들어가요), 배열, 그리고 구조체는 **자가 완결적(self-contained)**이에요. 이런 값은 자기 데이터를 완전한 복사본으로 그대로 갖고 있고, 이런 타입의 변수는 그 값을 통째로 저장해요. 예를 들어 배열 변수는 배열의 모든 요소를 위한 저장 공간, 즉 그 변수 자체를 제공하죠. 각 타입의 제로 값은 해당 타입에 특화된 값이고, 절대로 nil이 아니에요.

반대로 nil이 아닌 포인터, 함수, 슬라이스, 맵, 채널 값은 그 뒤에 있는 데이터에 대한 참조를 갖고 있는데, 그 데이터는 여러 값이 함께 공유할 수 있어요.

  • 포인터 값은 포인터의 베이스 타입 값을 담고 있는 변수를 가리키는 참조예요.
  • 함수 값은 (경우에 따라 익명일 수도 있는) 함수와, 그 함수가 감싸고 있는 변수들에 대한 참조를 담아요.
  • 슬라이스 값은 슬라이스의 길이, 용량, 그리고 그 기본 배열에 대한 참조를 담아요.
  • 맵 또는 채널 값은 맵이나 채널의 구현별 데이터 구조에 대한 참조예요.

인터페이스 값은 인터페이스의 동적 타입에 따라 자가 완결적일 수도, 뒤의 데이터에 대한 참조를 담을 수도 있어요. 값이 참조를 담을 수 있는 타입에서는 프리디클레어드 식별자 nil이 그 타입의 제로 값이에요.

여러 값이 같은 데이터를 공유할 때, 그중 한 값을 바꾸면 다른 값이 바뀔 수 있어요. 예를 들어 슬라이스의 한 요소를 바꾸면, 같은 배열을 공유하는 모든 슬라이스에서 기본 배열의 그 요소가 함께 바뀌죠.

더 알아보기

이 내용은 변수, 슬라이스 타입, 제로 값 같은 항목과 이어져 있어요. 값이 어떻게 저장되고 공유되는지 뼈대를 잡았으니, 이제 각 타입이 실제로 어떤 구조로 데이터를 다루는지 하나씩 따라가 보면 그림이 더 또렷해져요.