프로그래밍Go 개발자

Go에서 문자열(string)과 관련된 작업 시 예상치 못한 오류를 피하기 위해 알아야 할 특징은 무엇인가요?

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

답변.

질문 역사: Go에서 문자열(string)은 기본적이고 자주 사용되는 유형으로, 데이터 교환, 로깅, 파싱 등에 적극적으로 사용됩니다. Go의 특성은 문자열이 변경 불가능(immutable)하고, 변경할 수 없는 바이트의 시퀀스로 구성되며, UTF-8 형식의 데이터를 포함할 수 있다는 점입니다.

문제: 문자열과 바이트 슬라이스([]byte)에 대한 작업을 혼동하여 문자열을 변경할 때, 음운으로 잘라낼 때, 그리고 멀티바이트 문자를(예: 키릴 문자, 이모지) 다룰 때 오류를 발생시킵니다.

해결책:

문자열은 변경 불가능하여 직접 요소를 변경할 수 없습니다. (예: s[0]을 변경하려는 시도는 허용되지 않습니다.) 문자열은 UTF-8로 인코딩되므로, 하나의 문자(룬)는 하나의 바이트보다 클 수 있습니다. []byte와의 작업은 더 저렴하지만 수동적인 관리가 필요합니다. 문자열 <-> []byte 변환은 항상 복사본을 생성합니다.

코드 예시:

s := "안녕하세요" fmt.Println(len(s)) // 12 바이트 (한글: 바이트 당 2개) fmt.Println(len([]rune(s))) // 6 룬, 그러한 글자 수 fmt.Println(string([]byte{228, 189, 160, 229, 165, 189})) // 중국 한자

주요 특징:

  • 문자열은 변경 불가능하여 인덱스로 변경할 수 없습니다.
  • 문자열은 UTF-8로 인코딩되어 있으며, 항상 1 문자 = 1 바이트가 아닙니다.
  • 문자열 <-> []byte 변환은 복사본을 만듭니다.

함정 질문.

1. 인덱스를 통해 문자열의 특정 문자를 변경할 수 있습니까? (예: s[1] = 'a')

답변: 아니요. 문자열은 변경할 수 없으며, 컴파일러가 오류를 발생시킵니다. 새로운 []rune 또는 []byte 슬라이스를 생성하여 수정을 한 다음 다시 문자열로 변환해야 합니다.

2. 왜 len(str)는 항상 문자열의 문자 수와 일치하지 않나요?

답변: len(str)은 바이트 수이며, 룬(문자)의 수가 아닙니다. 키릴 문자 또는 이모지 등의 경우 긴 문자열이 직관적으로 예상하지 못한 값을 반환할 수 있습니다. 문자 수를 얻으려면 []rune을 사용합니다:

s := "세상 😀" fmt.Println(len(s)) // 7 fmt.Println(len([]rune(s))) // 5

3. 문자열은 함수로 값에 의해서 전송되나요, 참조에 의해서 전송되나요?

답변: 값에 의하여 전송되지만, 실제로는 메모리에 대한 포인터와 길이를 내부에 저장하고 있습니다. 전송 후 두 변수는 "같은" 텍스트를 가리키게 되며, 복사가 자동으로 생성되지 않습니다. 실제 메모리 복사는 []byte로 변환할 때 또는 []byte에서 문자열로 변환할 때 발생합니다.

전형적인 오류 및 안티 패턴

  • 인덱스를 통해 문자열을 직접 변경하려는 시도.
  • 유니코드와 관련한 오류를 피하기 위해 len을 이용하여 문자열 길이 비교.
  • 직렬화에 []byte를 사용하는 것, 그러나 인코딩을 까먹음.
  • 문자열과 []byte가 메모리에서 서로 다른 객체라는 것을 잊음.

실생활 예시

부정적인 케이스

개발자가 러시아 문자로 이루어진 문자열을 가졌고, 처음 4 바이트를 가져와 첫 번째 문자를 얻을 것이라고 기대하였으나, 실제로는 문자 반쪽만 얻어서 "손상된" 문자가 됩니다.

장점: 빠르고 간단하게 처리되었습니다. 단점: 유니코드 데이터와 잘못된 작업, "손상된" 문자열, 다른 곳에서 이러한 문자열을 파싱하려고 할 때 패닉이 발생합니다.

긍정적인 케이스

문자열을 []rune으로 변환하여 문자 작업을 수행하고, 필요한 작업 후 다시 string()을 통해 문자열로 조립합니다. []byte 작업은 낮은 수준의 직렬화에 대해서만 수행하며, 인코딩을 고려합니다.

장점: 올바른 유니코드 처리와 함수의 신뢰성. 단점: 약간 느리고 더 많은 메모리 요구하지만, 모든 문자열에 대해 안전합니다.