프로그래밍백엔드 개발자

Go에서 슬라이스 작업의 특징을 설명하십시오: nil 슬라이스란 무엇이며, 길이(length)와 용량(capacity) 사이의 차이점은 무엇이며, 데이터 유출이나 패닉 없이 슬라이스를 올바르게 증가시키는 방법은 무엇입니까?

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

답변.

슬라이스는 다이나믹 배열로, Go에서 배열 작업의 주요 구조 단위입니다. 역사적으로 프로그래밍 언어는 고정 배열이나 더 무거운 구조를 제공했습니다. Go는 자동 크기 관리와 길이 변경 기능으로 메모리 컬렉션에 대한 편리한 도구로 슬라이스를 구현했습니다.

문제는 메모리 관리, 경계 사례 처리(빈, nil, 가득 찬 슬라이스) 및 슬라이스의 길이와 용량 사이의 차이를 이해하는 것입니다.

해결책은 내장 함수 len(), cap()을 올바르게 사용하고 Go의 규칙에 따라 슬라이스를 조작하는 것입니다.

코드 예시:

var a []int // nil 슬라이스, len=0, cap=0 b := make([]int, 0) // 빈 슬라이스, len=0, cap=0 c := make([]int, 3, 5) // len=3, cap=5 c = append(c, 4, 5, 6) // cap가 자동으로 증가함

핵심 특징:

  • nil 슬라이스(var s []int)는 메모리를 전혀 할당하지 않으며, 빈 슬라이스(make([]int, 0))와는 내부적으로만 다릅니다.
  • 길이는 현재 요소 수를 나타내고, 용량은 추가 할당 없이 최대 요소 수입니다.
  • append를 사용할 때, 만약 용량이 부족하면 내부적으로 새로운 슬라이스가 생성되고, 기존 데이터는 변경되지 않습니다.

함정 질문.

nil 슬라이스에 append한 후 슬라이스의 길이와 용량은 얼마입니까?

nil 슬라이스(var s []int)에 대해 append(s, 1)을 수행하면 길이가 1, 용량이 1인 슬라이스가 됩니다. Go가 자동으로 저장소를 할당합니다.

var s []int s = append(s, 42) // s는 이제 [42], len=1, cap=1

nil 슬라이스의 용량에 접근할 수 있습니까?

예, nil 슬라이스의 경우 두 함수 lencap 모두 0을 반환합니다. 패닉이 발생하지 않습니다.

var s []int fmt.Println(len(s), cap(s)) // 0 0

nil 슬라이스에 대해 사전 할당 없이 인덱스에 요소를 할당하려고 하면 어떤 일이 발생합니까?

index out of range 패닉이 발생합니다. 슬라이스에 요소가 없기 때문입니다.

var s []int s[0] = 1 // panic: runtime error: index out of range

일반적인 오류 및 안티 패턴

  • nil 슬라이스 또는 빈 슬라이스를 필수 길이가 있는 함수에 전달할 때의 오류.
  • 용량 증가를 고려하지 않고 슬라이스를 덮어쓰거나 비논리적인 append 루프.
  • 요소 추가를 위해 append 대신 인덱스를 할당하려고 할 때.

실생활 사례

부정적인 케이스

팀이 Go 서버에서 var s []T를 사용하기로 결정하고 항상 make([]T, 0)과 동일하려고 했습니다. 결과적으로 일부 JSON 직렬화가 null을 반환했습니다.

장점:

  • 초기 메모리 할당이 줄어듭니다.

단점:

  • JSON이 올바르게 작동하지 않음(결과적으로 null이 배열 대신 도착함).
  • 인덱스에 접근 시 런타임 오류 발생.

긍정적인 케이스

make([]T, 0, 100)을 사용하여 사전 할당한 후, 반복문에서 append만 사용하는 것입니다. 이렇게 하면 메모리 할당이 최소화되고 속도에서 이점을 얻을 수 있습니다.

장점:

  • 메모리 효율적 작업.
  • 직렬화 시 패닉이나 예기치 않은 값 없음.

단점:

  • 예상 요소 수가 설정된 용량과 일치하지 않으면 메모리 남용이 발생할 수 있습니다.