더북(TheBook)

주소 연산자(&)로 메모리 주소 할당

변수 앞에 주소 연산자(&)를 붙이면 변수의 메모리 주소를 알아낼 수 있고, 알아낸 메모리 주소를 포인터 변수에 할당해서 사용할 수 있다.

var p *int

i := 1
p = &i
fmt.Println(i)  // 1
fmt.Println(&i) // 0x1043617c
fmt.Println(*p) // 1
fmt.Println(p)  // 0x1043617c

이 코드에서 볼 수 있듯이 int 타입인 변수 i와 포인터 변수 p는 동전의 양면과 같다. i는 값을 갖고 있고 pi의 주소를 갖고 있다. i& 연산자를 붙이면 주소를 알아낼 수 있고, p* 연산자를 붙이면 값을 알아낼 수 있다. 즉, i*p와 같고 &ip와 같다. 그래서 *pint 타입 변수처럼 사용할 수 있다.

var p *int
var pp **int
 
i := 1
p = &i
pp = &p
fmt.Println(i, *p, **pp) // 1 1 1
 
i += 1
fmt.Println(i, *p, **pp) // 2 2 2
 
*p++
fmt.Println(i, *p, **pp) // 3 3 3
 
**pp++
fmt.Println(i, *p, **pp) // 4 4 4

선언과 동시에 초기화할 수도 있다.


type rect struct{ w, h float64 }
 
var i int = 1
var p *int = &i
var s *rect = &rect{1, 2}
 
fmt.Println(p)
fmt.Println(s)

실행 결과

0x82000a260 &{1 2}

구조체 포인터를 출력하면 포인터가 가리키는 값과 포인터인 것을 나타내기 위해 &{1 2}처럼 주소 연산자(&)를 함께 출력한다(구조체는 4장 객체 지향 프로그래밍에서 설명한다)

일반 변수와 마찬가지로 선언과 동시에 값을 할당하는 경우 타입을 생략할 수 있다.

var p1 = &i
var s1 = &rect{1, 2}
 
s2 := &rect{1, 2}
p2 := &i

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.