개발자의 오르막
GoLang 의 포인터 본문
포인터란?
- 포인터는 메모리 주소를 값으로 갖는 타입을 의미
- 변수의 주소 또한 메모리 주솟값 또는 숫자값이기 때문에 다른 변수의 값으로 사용될 수 있음
- 메모리 주솟값을 변숫값을 가질 수 있는 변수를 포인터 변수라 함
- 메모리 주소를 값으로 가져 메모리 공간을 가리키는 타입을 포인터라 한다.
- 포인터가 가리키는 값을 가져오는 것을 역참조라 한다.
포인터의 변수 선언
- 포인터 변수는 가리키는 데이터 타입 앞에 *를 붙여서 선언
- var p *int
- p는 int 타입 데이터의 메모리 주소를 가리키는 포인터 변수
- 포인터의 기본값은 nil
- 포인터 사용예시
package main
import "fmt"
func pointer() {
var a int = 500
var p *int
p = &a
fmt.Printf("p의 값: %p\\n", p)
fmt.Printf("p가 가리키는 메모리의 값: %d\\n", *p)
*p = 100
fmt.Printf("a의 값: %d\\n", a)
}
func main() {
pointer()
}
- 위처럼 a 의 변수에 값 500 을 갖고 있는 변수이며, p 는 a의 포인터 변수이다.
- *p를 통해 역참조로, p가 가리키는 변수의 값을 출력한다.
- *p = 100 으로 p가 가리키는 a 변수의 값을 변경할 수 있다.
포인터는 왜 써요?
- 변수 대입이나 함수 인수 전달은 항상 값을 복사하기 때문에 많은 메모리 공간을 사용하는 문제와 큰 메모리 공간을 복사할 때 발생하는 성능 문제를 안고 있습니다.
- 또한 다른 공간으로 복사되기 때문에 변경 사항이 적용되지도 않습니다.참조 : Tucker 의 Go 언어프로그래밍
- 그러나 포인터를 활용한 경우에는 이미 선언했던 변수의 메모리를 그대로 활용할 수 있으며, 역참조를 통해 해당 메모리에 저장된 변수 값을 활용할 수 있다.
- 또한 그 메모리에 저장된 값을 변경할 수 있어, Micro 서비스를 구축할 때 메모리 활용을 포인터를 통해 극대화할 수 있다.
Pointer를 언제 써야 하나? : 값복사가 발생하여 메모리를 낭비하고 싶지 않을 때
- AS-IS (변수에 값 대입 연산자를 사용)
package main
import "fmt"
type Data struct {
value int
data [200]int // 200개의 원소를 가진 int형 배열
}
func ChangeData(d Data) {
// 새로운 변수 메모리에 값이 복사되고 있음
d.value = 999;
d.data[100] = 999;
}
func main() {
var data Data
// 함수의 인자로 전달되면서 함수 스코프 내의 지역변수로 값 복사(메모리 사용)
// struct의 크기는 201 * 8 바이트 만큼 할당됨.
// 이 함수가 호출될 때마다 복사되어 메모리 낭비가 빈번히 일어남
ChangeData(data)
fmt.Println(data.value)
fmt.Println(data.data[100])
}
- TO-BE (포인터를 활용)
// 포인터를 받아서 활용함. 포인터는 커봐야 8바이트임. 용량 절약 꿀!
func ChangeData(d *Data) {
// 위에서 역참조로 가져온 값을 d 로 선언했기 때문에 역참조로 동작함
d.value = 999;
d.data[100] = 999;
}
func main() {
var data Data
// 변형할 데이터의 주소값을 넘김.
// 포인터의 크기인 메모리 주소는 64비트 컴퓨터에선 8바이트, 32비트 컴퓨터에선 4바이트사용
ChangeData(&data)
fmt.Println(data.value) // 999
fmt.Println(data.data[100]) // 999
}
- AS-IS 에서 ChangeData 를 호출할 때마다 값 복사가 일어나므로 메모리를 효율적으로 사용하지 못함
- 포인터를 활용하게 되면, 포인터가 값복사가 되는데, 포인터는 8바이트밖에 안되서 메모리 효율이 좋음
'GoLang' 카테고리의 다른 글
Go, Makefile, Docker로 프로젝트 셋팅 및 빌드 정보 활용하기 (0) | 2022.10.08 |
---|---|
Golang 과 TDD (0) | 2022.10.02 |
golang과 Docker로 환경변수 제어하기 (0) | 2022.08.23 |
redis: discarding bad PubSub connection: redis: ping timeout 이슈 (0) | 2022.06.17 |
고루틴과 동시성 프로그래밍 (0) | 2022.05.18 |
Comments