정수 리터럴

정수 리터럴

코드에서 숫자 값이 필요할 때, 우리는 보통 42처럼 10진법으로 적어요. 그런데 색상 코드나 접근 권한 비트처럼 2진법·16진법으로 보는 게 훨씬 자연스러운 값들도 꽤 있죠. Go가 이런 상황에서 어떤 표기를 지원하는지, 또 숫자 사이에 밑줄(_)을 넣는 게 어떤 의미인지, 실제 리터럴 예시와 함께 하나씩 살펴볼게요.

출처: Go Specification

본문

정수 리터럴(integer literal)은 정수 상수를 나타내는 숫자의 나열이에요. 선택적인 접두사를 붙이면 10진법이 아닌 다른 진법을 지정할 수 있어요.

  • 0b 또는 0B는 2진법을 뜻해요.
  • 0, 0o, 또는 0O는 8진법을 뜻해요.
  • 0x 또는 0X는 16진법을 뜻하죠 [Go 1.13].

여기서 단독으로 쓰인 0 하나는 10진법의 0으로 취급합니다. 그리고 16진법 리터럴에서는 문자 a부터 f, A부터 F까지가 각각 값 10부터 15를 나타내요.

읽기 좋게 하려는 목적으로, 밑줄 문자 _를 밑줄 접두사 뒤나 연속된 숫자 사이에 넣을 수 있어요. 이런 밑줄은 리터럴의 값을 바꾸지 않아요. 아래 EBNF가 정확한 문법을 보여주는데, 자세히 보면 밑줄이 어디에 들어갈 수 있는지가 명확하게 드러나요.

int_lit        = decimal_lit | binary_lit | octal_lit | hex_lit .
decimal_lit    = "0" | ( "1" … "9" ) [ [ "_" ] decimal_digits ] .
binary_lit     = "0" ( "b" | "B" ) [ "_" ] binary_digits .
octal_lit      = "0" [ "o" | "O" ] [ "_" ] octal_digits .
hex_lit        = "0" ( "x" | "X" ) [ "_" ] hex_digits .

decimal_digits = decimal_digit { [ "_" ] decimal_digit } .
binary_digits  = binary_digit { [ "_" ] binary_digit } .
octal_digits   = octal_digit { [ "_" ] octal_digit } .
hex_digits     = hex_digit { [ "_" ] hex_digit } .

이제 실제 예시를 볼게요. 같은 값을 밑줄을 넣고 빼고, 서로 다른 진법으로 적은 모습이에요.

42
4_2
0600
0_600
0o600
0O600       // second character is capital letter 'O'
0xBadFace
0xBad_Face
0x_67_7a_2f_cc_40_c6
170141183460469231731687303715884105727
170_141183_460469_231731_687303_715884_105727

_42         // an identifier, not an integer literal
42_         // invalid: _ must separate successive digits
4__2        // invalid: only one _ at a time
0_xBadFace  // invalid: _ must separate successive digits

예시 끝부분의 주석을 꼭 한 번 읽어보세요. 여기서 규칙의 경계가 드러나요. _42는 밑줄이 맨 앞에 붙어서 정수 리터럴이 아니라 식별자(identifier) 가 되어 버려요. 42_처럼 숫자가 밑줄로 끝나면, 4__2처럼 밑줄이 두 번 겹치면, 0_xBadFace처럼 접두사 바로 뒤에 밑줄이 오면 모두 잘못된 문법이에요. 밑줄은 오직 연속된 숫자를 구분하는 데만 쓰인다는 점이 핵심이죠.

더 알아보기