프로그래밍백엔드 개발자

Go에서 포인터(pointers) 작업의 특징에 대해 설명하십시오: 언제 사용해야 하며, 다른 언어의 참조와 어떤 차이점이 있으며, 그 사용과 관련된 전형적인 함정은 무엇입니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

Go에서 포인터는 다른 변수의 주소를 저장하는 변수입니다. 일부 언어와 달리 Go에서는 포인터 산술을 수행할 수 없어 더 안전하게 사용됩니다. Go에서 포인터는 주로 다음과 같은 경우에 사용됩니다:

  • 큰 구조체를 함수로 전달할 때 (복사를 피하기 위해).
  • 외부 함수에서 객체를 수정할 때.
  • 복잡한 데이터 구조(예: 리스트, 트리)를 구현할 때.

Go는 C++와 같은 참조 타입에 대한 명시적 지원이 없지만, 슬라이스와 맵은 본질적으로 참조형이므로 일반적으로 값으로 전달됩니다.

포인터 및 값 전달 예:

package main import "fmt" type User struct { Name string } func changeNameByValue(u User) { u.Name = "바샤" } func changeNameByPointer(u *User) { u.Name = "페티아" } func main() { user := User{Name: "이반"} changeNameByValue(user) fmt.Println(user.Name) // 이반 changeNameByPointer(&user) fmt.Println(user.Name) // 페티아 }

곤란한 질문.

Go에서 포인터가 상수나 리터럴을 가리킬 수 있습니까?

정답: 아니요, Go에서는 상수나 리터럴의 주소를 직접 가져올 수 없습니다. 주소는 오직 변수에서만 가져올 수 있습니다:

x := 5 p := &x // OK p2 := &10 // 컴파일 오류

이는 유사한 언어와 혼동될 수 있습니다.

주제의 미세한 차이를 알지 못해서 발생한 실제 오류의 예.


이야기

한 프로젝트에서 개발자는 슬라이스의 요소에 대한 참조를 전달하려고 했고, 포인터를 사용하여 슬라이스를 안전하게 수정할 수 있다고 생각했습니다. 그러나 잘못된 판단이었습니다: 슬라이스 자체가 포인터를 포함하는데, append() 후에는 기초 배열의 주소가 변경되어 변경사항이 원본 데이터에 항상 반영되지 않았습니다. 이로 인해 수정하기 어려운 버그가 발생했습니다(데이터가 "사라졌습니다").


이야기

프로젝트에서 반복문에서 지역 변수에 대한 포인터 목록이 생성되었고, 반복문이 끝난 후 모든 포인터가 동일한 변수(반복 변수)를 가리키고 있었습니다. 오류는 프로덕션에서 충돌이 발생한 후에야 발견되었습니다.


이야기

개발자는 포인터 할당이 이전 객체를 메모리에서 해제한다고 잘못 결론내리고, 명시적으로 포인터에 nil을 할당하여 즉시 GC가 발생하기를 기대했습니다. 실제로 Go에서는 가비지 수집기가 객체를 청소할 시기를 스스로 결정하며, 이전에 참조를 무효화하는 것을 무시합니다. 이로 인해 적시에 메모리 해제를 기대했던 곳에서 메모리 누수가 발생했습니다.