본문 바로가기
프로그래밍/Golang

Golang 값을 전달할까, 포인터를 전달할까?

by slowin 2024. 8. 2.

개요

Go 언어를 사용하다 보면 함수에 값을 전달할지, 아니면 포인터를 전달할지 고민하게 되는 상황이 자주 발생합니다.Go에서 값 전달과 포인터 전달의 차이점을 이해하고, 각각의 장단점을 비교하여 어떤 경우에 무엇을 선택해야 하는지 알아보겠습니다.

 

값 전달 (Pass by Value)

값 전달은 함수에 인수를 전달할 때 그 값을 복사하여 전달하는 방식입니다. 이 경우 함수 내에서 인수의 값을 변경해도 원본 값에는 영향을 미치지 않습니다.

 

장점

  1. 안전성: 값이 복사되므로 함수 내에서 값이 변경되더라도 원본 데이터가 보호됩니다.
  2. 단순성: 포인터를 사용하지 않으므로 코드가 단순하고 직관적입니다.

단점

  1. 성능 문제: 큰 구조체나 배열을 복사할 때 메모리 사용량이 증가하고 성능이 저하될 수 있습니다.
  2. 변경 불가: 함수 내에서 값을 변경하더라도 원본 데이터는 변경되지 않으므로, 함수 호출 후 변경된 값을 반영할 수 없습니다.

 

포인터 전달 (Pass by Pointer)

포인터 전달은 함수에 인수를 전달할 때 그 값의 주소를 전달하는 방식입니다. 이 경우 함수 내에서 포인터를 통해 원본 값을 직접 변경할 수 있습니다.

 

장점

  1. 성능: 큰 구조체나 배열을 포인터로 전달하면 메모리 복사 비용이 줄어들어 성능이 향상됩니다.
  2. 변경 가능: 함수 내에서 값을 변경하면 원본 데이터도 변경되므로, 함수 호출 후에도 변경된 값을 반영할 수 있습니다.

단점

  1. 안전성 문제: 포인터를 잘못 사용하면 nil 포인터 참조나 메모리 손상 등의 문제가 발생할 수 있습니다.
  2. 복잡성: 포인터를 사용하면 코드가 복잡해지고, 메모리 관리에 신경 써야 합니다.

언제 값을 전달하고, 언제 포인터를 전달해야 할까?

1. 작은 크기의 데이터: 기본 데이터 타입(int, float 등)이나 작은 구조체는 값을 전달하는 것이 일반적입니다. 값 복사 비용이 낮고 코드가 간단해지기 때문입니다.

func doubleValue(x int) int {
    return x * 2
}

 

2. 큰 구조체나 배열: 큰 구조체나 배열은 포인터로 전달하는 것이 좋습니다. 메모리 복사 비용을 줄이고 성능을 향상시킬 수 있습니다.

type LargeStruct struct {
    data [1000]int
}

func modifyLargeStruct(ls *LargeStruct) {
    ls.data[0] = 100
}

 

3. 변경이 필요한 경우: 함수 내에서 인수의 값을 변경해야 할 경우 포인터를 사용합니다. 이렇게 하면 함수 호출 후에도 변경된 값이 반영됩니다.
func increment(x *int) {
    *x = *x + 1
}
4. 안정성과 단순성: 데이터의 안전성이 중요하고, 함수 내에서 데이터가 변경될 필요가 없는 경우에는 값을 전달하는 것이 좋습니다.