[Go] Pointer

김무연·2025년 1월 22일

포인터

Go언어에서는 항상 값을 전달한다

포인터란 메모리 주소를 저장하는 변수 타입이다. Go 언어에서 모든 데이터는 값의 전달 (pass by value) 로 작동한다. 즉 reference 방식이 아닌, 전달해야 할 데이터의 원본이 아닌 복사본을 만들어 전달한다.
반면 포인터는 값을 전달하지 않고 원본 데이터의 메모리 주소 정보를 전달한다. 그래서 전달받은 곳에서는 데이터의 메모리 주소 정보로 접근하여 데이터를 확인할 수 있다. (허나 메모리 주소 또한 값이다)
포인터는 오직 한가지 목적을 가지고 있다. "공유". 프로그램의 경계를 가로질러 값을 공유하는 것이다. 여러 종류의 프로그램 경계가 있는데, 가장 흔한 것은 함수 호출이다. 고루틴 사이에도 경계가 있을 수 있다.

Pass by Value vs Pass by Reference

  1. Pass by Value (값 복사)

    함수에 인자를 전달할 때, 인자의 값을 복사하여 함수에 전달하는 방식, 함수 내에서 인자의 값이 변경되더라도 원본 데이터에는 영향을 미치지 않음

  • 각 함수 호출시 인자의 복사본이 생성됨
  • 복사본이 생성되므로 인해 메모리 사용량 증가
  • 원본 데이터에는 변경 x
package pass

import "fmt"

type Person struct {
	name string
	age int
	gender bool
}

func changeName(p Person) Person {
	p.name = "구마적"
	return p
}

func Pass() {
	p := Person{name: "김두한", age : 30, gender : true}
	copy := changeName(p)
	fmt.Printf("복사 = %v\n", copy)
	fmt.Printf("원본 = %+v\n", p)
}
  1. Pass by Reference

    함수에 인자를 전달할 때, 인자의 메모리 주소를 전달하는 방식, 이러한 경우 함수내에서 인자의 값을 변경하면 원본 데이터도 변경됨

  • 메모리 주소가 전달되므로 복사본이 아님
  • 대용량 데이터 구조체를 전달할 때 성능이 향상 됨
  • 원본 데이터가 변경되므로 큰 주의 필요

허나 아래의 코드를 보면 어떨까? changedName으로 주소값을 넘기고 있으니 pass by value인것 같지만, Go는 무조건 pass by value로 동작한다고 했는데..., 아래의 코드는 엄밀히 말하면 pass by value이다. 주소도 또한 값이기 때문에, 주소를 인자로 넘기고 있지만, 실상적으로는 주소라는 '값'을 넘기고 있는 것이다. 즉 방식은 pass by value이지만 원본 데이터의 접근과 수정을 가능하게 하는법이라고 할 수 있겠다.

package pass

import "fmt"

type PersonRef struct {
	name string
	age int
	gender bool
}

func changedName(p *PersonRef) {
	// 단순히 주소값을 받아와 해당 주소값의 value를 변화시키는 것
	p.name = "구마적"
}

func Passbyref() {
	pref := PersonRef{
		name : "김두한",
		age : 23,
		gender : false,
	}
	// 주소를 전달하지만, 이것 역시 "pass by value"로 작동, 즉 주소라는 값을 전달하는 것
	changedName(&pref)

	fmt.Printf("참조시원본 = %+v\n", pref)
}

포인터 변수의 크기

포인터 변수의 크기는 uintptr이라는 데이터 타입으로 이루어 지는데, 이 타입은 포인터 주솟값 자체를 담을수 있는 데이터 타입이다. 결국에는 uint이기 때문에 cpu 아키텍쳐에 따라 64bit 체제면 8byte 32bit체제면 4byte가 된다.

profile
Notion에 정리된 공부한 글을 옮겨오는 중입니다... (진행중)

0개의 댓글