Go는 C와 많은 부분이 유사하다.


타 언어는 참조 자료형 등으로 메모리 직접 접근을 막아두는데,

Go는 C처럼 자유롭고 위험하게 메모리를 사용할 수는 없지만 포인터로 직접 메모리를 다룰 수 있다.





C의 포인터와 동일하게 메모리의 어느 부분을 가리키는 자료형이며, 참조/역참조로 사용하지만 포인터 연산은 불가능하다.

64비트 시스템에서 8바이트이다.



Go의 몇몇 자료형은 내부적으로 포인터로 동작한다.

함수 인자 전달이나 반환은 데이터를 이동시킬 때 값을 복사하는데,

포인터나 포인터 사용 자료형을 써야 대량의 데이터도 빠르게 옮길 수 있다.


string은 UTF-8 byte 배열에 대한 포인터다. {길이 int, 포인터}로 구성되어 string 변수 자체는 항상 16바이트이다.


map도 해시맵 본체에 대한 포인터다.


slice는 정적 배열(길이 불변)에 대한 포인터다. {시작 지점 포인터, 슬라이스 길이 int, 정적 배열 용량 int}로 구성된다.

슬라이스의 값을 바꾸면 정적 배열의 값이 바뀌는 것이고,

값을 추가하면 정적 배열의 용량을 채울 때까진 계속 그 배열을 사용한다.

용량이 부족해지면 더 큰 정적 배열을 만들어 값을 복사한다.


string, map, slice는 내부적으로 포인터이기 때문에 보통은 *string처럼 추가로 포인터를 만들 필요가 없다.



내부적으로 포인터인 자료형을 사용할 때는 이것이 올바른 포인터인지 주의해야 한다.

make로 초기화하지 않은 map은 널 포인터라서 사용할 수가 없다.



특히 슬라이스 사용 시에 정적 배열을 공유하는 경우에 조심해야 한다.

data0, data1은 같은 share 배열을 가리키고 있어서 data0의 값을 바꾸니 data1도 영향을 받았다.

멀티스레딩처럼 데이터 공유 환경에서 문제가 많이 터진다.



구조체를 가리키는 포인터는 필드나 메소드 사용 시에 자동으로 역참조를 해 준다.



메소드 사용 시 구조체를 값 복사로 받을 수도 있고 포인터로 받을 수도 있는데,

원본 구조체의 값을 바꾸려면 포인터로 받아야 한다.




Go의 포인터는 메모리를 만지는 느낌도 나고 C처럼 머리아프지도 않아서 참 좋은 것 같다.