Go 포인터(pointer)

Go 포인터(pointer)

포인터(pointer)

포인터는 변수가 저장된 메모리의 주소이다. C 언어와 마찬가지로 객체의 포인터를 참조하려면 &를, 포인터의 내용을 참조하려면 *를 사용한다.

package main

import "fmt"

func main() {
	var a1 int  // int 타입 변수 a1 정의
	var p1 *int // int에 대한 포인터 변수 p1 정의

	p1 = &a1  // p1에 a1의 포인터를 설정
	*p1 = 123 // 포인터의 내용(즉, a1)에 123을 대입.

	fmt.Println(a1)
	fmt.Println(p1)
	fmt.Println(*p1)
}

실행 결과:

123
0xc00001c030
123

변수의 값을 전달하는 것을 “값 전달한다"고 하고, 변수의 포인터를 전달하는 것을 “참조 전달한다"고 한다.
값을 전달하면 값의 복사본만 전달하므로 원래 변수를 변경할 수는 없지만, 포인터를 전달하면 함수에서 변수의 값을 변경할 수 있다.

package main

import "fmt"

func main() {
	var a1 int = 123
	var a2 int = 123
	fn(a1, &a2)         // a1은 값을 전달하고, a2는 참조 전달한다.
	fmt.Println(a1, a2)
}

func fn(b1 int, b2 *int) {
	b1 = 456
	*b2 = 456
}

실행 결과:

123 456

연산자 .는 구조체의 멤버 변수나 포인터가 가리키는 구조체의 멤버 변에서 액세스할 수 있습니다.

package main

import "fmt"

type Person struct {
	name string
	age  int
}

func main() {
	a1 := Person{"devkuma", 23} // 구조체 Person의 객체 a1을 확보하고 초기화
	p1 := &a1                   // 구조체 a1에 대한 포인터를 p1에 저장
	fmt.Println(a1.name)        // 멤버 변수에는 왼쪽과 같이 액세스
	fmt.Println((*p1).name)     // 포인터 p의 내용(structure)의 멤버 변수에는 왼쪽과 같이 액세스
	fmt.Println(p1.name)        // 다만, Go 언어에서는 이를 왼쪽 같이도 기술할 수 있다
}

실행 결과:

devkuma
devkuma
devkuma

영역 확보(new)

new()를 사용해 영역을 동적으로 확보하여, 그 영역에의 포인터를 얻을 수가 있다. 확보된 영역은 참조되지 않게 된 후에는 가비지 콜렉션에 의해 자동적으로 해제된다.

package main

import "fmt"

type Book struct {
	title string
}

func main() {
	bookList := []*Book{}

	for i := 0; i < 10; i++ {
		book := new(Book)
		book.title = fmt.Sprintf("Title#%d", i)
		bookList = append(bookList, book)
	}
	for _, book := range bookList {
		fmt.Println(book.title)
	}
}

실행 결과:

Title#0
Title#1
Title#2
Title#3
Title#4
Title#5
Title#6
Title#7
Title#8
Title#9



최종 수정 : 2023-03-26