프로그래밍백엔드 개발자

Go에서 암묵적으로 타입이 지정되지 않은 상수(untyped constants)는 어떻게 작동하며, 타입이 지정된 상수(typed constants)와는 어떻게 다른가요? 이 측면이 계산, 인터페이스 및 함수 전달에 있어 왜 중요할까요?

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

답변.

Go에는 암묵적으로 타입이 지정되지 않은 상수(untyped)와 명시적으로 타입이 지정된 상수(typed)라는 두 가지 종류의 상수가 있습니다. 이는 언어가 타입 시스템을 유연하고 안전하게 만들고, 컴파일러가 컴파일 시점에 오류를 식별하며, 허용된 곳에만 타입 변환을 보장하는 것과 관련이 있습니다.

문제는 프로그래머가 이 두 가지 범주를 구별하지 않고 상수의 동작에 의존할 때 발생하며, 이는 함수 및 인터페이스 선언에서의 타입 요구 사항을 간과하게 될 수 있습니다. 이는 타입 간 변환 오류, 예상치 못한 컴파일 오류 또는 함수 호출 시 예상치 못한 "튀는" 호환성 문제를 초래할 수 있습니다.

해결책은 다음과 같이 명확한 이해가 필요합니다:

  • 특정 타입에 할당되지 않는 한 상수는 고정 타입이 없으며, 함수에 전달될 때 기대되는 타입에 맞춰 "조정"될 수 있습니다.
  • 타입을 지정하면 (예: const x int = 42) 이후에 이 상수를 사용하는 것은 지정된 타입으로 제한됩니다.

코드 예시:

const Pi = 3.14 // 암묵적으로 타입이 지정됨 const Answer int64 = 42 // 명시적으로 타입이 지정됨 func printInt(a int) { fmt.Println(a) } func main() { printInt(Pi) // 오류: Pi는 int가 아님 (하지만 명시적으로 변환 가능) printInt(int(Pi)) // 괜찮음 printInt(Answer) // 괜찮음, 왜냐하면 Answer는 이미 int64이며, int64에서 int로의 변환은 명시적 변환임 }

주요 특징:

  • 암묵적으로 타입이 지정된 상수는 타입 변환의 유연성을 제공합니다.
  • 명시적으로 타입이 지정된 상수는 지정된 타입에 단단히 고정됩니다.
  • 상수와 관련된 많은 작업은 변수와의 작업과 다르며, 컴파일 시점에서 더 많은 최적화와 오버플로우 검사가 가능합니다.

헷갈리는 질문들.

암묵적으로 타입이 지정된 상수를 int 타입의 변수에 부동 소수점 값으로 할당할 수 있나요?

아니요. 암묵적으로 타입이 지정된 상수는 다른 타입의 식에 사용될 수 있지만, float 상수를 int 타입의 변수에 할당하려고 하면 컴파일 오류가 발생합니다. 명시적 변환이 필요합니다:

const Pi = 3.14 var x int = Pi // 컴파일러 오류 발생 var y int = int(Pi) // 괜찮음

암묵적으로 타입이 지정된 상수는 첫 번째 할당 시점에 타입을 얻나요?

아니요, 상수는 특정 타입이 예상되는 컨텍스트에 삽입되거나 명시적으로 선언될 때까지 타입을 갖지 않습니다. 그 외의 경우에는 여전히 untyped입니다.

암묵적 타입의 큰 숫자 상수를 값이 맞는 경우 작은 크기의 변수 초기화에 사용할 수 있나요?

예, 절대값이 대상 타입의 범위 안에 있다면 가능합니다. 그렇지 않으면 컴파일러가 오버플로우 오류를 발생시킵니다.

예시:

const Big = 1 << 62 var x int32 = Big // 오류: Big이 int32에 맞지 않음 var y int64 = Big // 괜찮음

일반적인 오류 및 안티 패턴

  • 암묵적으로 타입이 지정된 상수와 명시적으로 타입이 지정된 상수 간의 차이를 무시
  • 허용된 타입 범위를 넘어 상수 값을 할당하거나 사용하는 시도
  • 예상되는 타입을 정의하지 않고 숫자 리터럴을 무분별하게 사용

실제 사례

부정적인 사례

복잡한 금융 프로젝트에서 개발자들은 여러 상수(비율, 계수)를 암묵적으로 타입이 지정되지 않게 선언했습니다. 어느 날 일부 함수가 float32 대신 float64를 요구하게 되었습니다. 자동 타입 조정으로 인해 계산의 정확도가 손실되었지만 즉시 발견되지 않았습니다.

장점:

  • 상수를 유연하고 쉽게 선언할 수 있음

단점:

  • 정확성 손실이 명확하지 않음
  • 기대되는 타입을 추적하지 않으면 오류가 발생함

긍정적인 사례

시스템의 다른 부분에서는 모든 상수가 명시적으로 타입 선언을 통해 정의되고 변환이 명시적으로 이루어졌습니다:

const Discount float64 = 0.05

장점:

  • 정확성 손실 가능성이 적음
  • 컴파일러가 즉시 범위 또는 타입 오류를 알려줌

단점:

  • 코드가 조금 더 많음
  • 서로 다른 타입에 대해 하나의 상수를 재사용하기가 불편함