var numPtr *int // 포인터형 변수를 선언하면 nil로 초기화됨
fmt.Println(numPtr) // nil
var numPtr *int = new(int)
fmt.Println(numPtr) // 0xc0820062d0: 메모리 주소. 시스템 마다, 실행할 때마다 달라짐
결과
0xc0820062d0
new 함수는 지정한 자료형의 크기에 맞는 메모리 공간을 할당한다. Go 언어는 메모리를 관리해주는 가비지 컬렉션을 지원하므로 메모리를 할당한 뒤 해제하지 않아도 된다.
포인터형 변수에 값을 대입하거나, 가져오려면 역참조(dereference)를 사용한다
var numPtr *int = new(int) // new 함수로 공간 할당
*numPtr = 1 // 역참조로 포인터형 변수에 값을 대입
fmt.Println(*numPtr) // 1: 포인터형 변수에서 값을 가져오기
실행결과
1
numPtr = 1은 numPtr에 저장된 메모리 주소로 접근하여 값을 대입, 그리고 numPtr은 numPtr에 저장된 메모리 주소에 접근하여 값을 가져온다
일반 변수에 참조(레퍼런스)를 사용하면 포인터형 변수에 대입할 수 있다.
&변수명
var num int = 1
var numPtr *int = &num // 참조로 num 변수의 메모리 주소를 구하여
// numPtr 포인터 변수에 대입
fmt.Println(numPtr) // 0xc0820062d0: numPtr 포인터 변수에 저장된 메모리 주소
fmt.Println(&num) // 0xc0820062d0: 참조로 num 변수의 메모리 주소를 구함
결과
0xc0820062d0
0xc0820062d0
변수 앞에 &를 붙이면 해당 변수의 메모리 주소를 뜻하며, 포인터형 변수에 대입할 수 있다.
Go 언어에서는 메모리 주소를 직접 대입하거나 포인터 연산을 허용하지 않으며,다음과 같이 메모리 주소를 직접 조작할 수는 없다
var numPtr *int = new(int)
numPtr++ // 컴파일 에러. 포인터 연산은 허용하지 않음
numPtr = 0xc0820062d0 // 컴파일 에러. 메모리 주소를 직접 대입할 수 없음
fmt.Println(numPtr)
func hello(n int) {
n = 2 // 매개변수 n에 2를 대입
}
func main() {
var n int = 1
hello(n) // 1이 들어있는 변수 n을 hello 함수에 넘김
fmt.Println(n) // 1: hello 함수안의 n에 2를 대입했지만 바깥의 n은 영향이 없음
}
실행결과
1
func hello(n *int) {
*n = 2 // 포인터 변수 n를 역참조하여 메모리에 2를 대입
}
func main() {
var n int = 1
hello(&n) // 1이 들어있는 변수 n의 메모리 주소를 hello 함수에 넘김
fmt.Println(n) // 2: hello 함수에서 n의 메모리 공간에 2를 대입했으므로 바깥에 있는 n의 값이 바뀌었음
}
실행결과
2
hello 함수에서 포인터형 매개변수를 받은 뒤 *를 사용하여 값을 2로 변경. 이렇게 하면 함수 바깥의 n의 값도 2가 된다. 즉, 메모리 주소를 넘겨주었으므로 기존 변수의 값이 바뀌게 된다