기본 식

기본 식 (Primary Expressions)

식(expression)을 처음 본다면, Go에서는 어떤 '표현'이든 결국 단항 연산이나 이항 연산의 피연산자(operand)로 쓰여요. 그런데 그 피연산자가 되는 것들 자체가 사실 나름의 구조를 갖고 있는데, 그걸 묶어서 **기본 식(Primary expressions)**이라고 불러요. 다른 연산자가 개입하기 전에 가장 먼저 평가되는, 가장 '원자적'인 단위라고 생각하면 돼요.

예를 들어 m["foo"]처럼 맵에서 값을 꺼내는 인덱스나, f(3.1415, true)처럼 함수를 호출하는 동작, obj.color처럼 필드를 고르는 셀렉터까지 — 겉보기엔 전부 '피연산자'처럼 보이지만 실제로는 그 안에 또 하위 구조가 있는 표현들이에요. 이 장에서는 이런 기본 식들이 어떤 문법으로 구성되는지 규칙(grammar)을 통해 정리해 볼게요.

출처: Go Specification

본문

기본 식은 단항 연산과 이항 연산의 피연산자가 되는 표현들입니다.

아래는 기본 식의 문법 규칙인데요, 이 규칙을 한 번 천천히 뜯어보면 어떻게 조합되는지가 보여요. PrimaryExpr는 그 자체만으로 완성될 수 있고(OperandConversion처럼), 아니면 이미 만들어진 PrimaryExpr 뒤에 셀렉터(.identifier), 인덱스([...]), 슬라이스([i:j]), 타입 단언(.(Type)), 인자 목록((...))을 하나씩 붙여서 확장해 나갈 수 있어요. 그래서 f.p[i].x()처럼 PrimaryExpr가 연쇄적으로 이어지는 모양이 가능한 거예요.

PrimaryExpr   = Operand |
                Conversion |
                MethodExpr |
                PrimaryExpr Selector |
                PrimaryExpr Index |
                PrimaryExpr Slice |
                PrimaryExpr TypeAssertion |
                PrimaryExpr Arguments .

Selector      = "." identifier .
Index         = "[" Expression [ "," ] "]" .
Slice         = "[" [ Expression ] ":" [ Expression ] "]" |
                "[" [ Expression ] ":" Expression ":" Expression "]" .
TypeAssertion = "." "(" Type ")" .
Arguments     = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .

문법 규칙만 봐서는 감이 안 잡힐 수 있으니, 실제 기본 식의 예시를 몇 개 볼게요. 대충 보면 각 줄이 PrimaryExpr 하나씩에 해당한다는 걸 알 수 있어요.

x
2
(s + ".txt")
f(3.1415, true)
Point{1, 2}
m["foo"]
s[i : j + 1]
obj.color
f.p[i].x()

여기서 2처럼 그저 값 하나인 경우는 그 자체로 Operand가 되는 기본 식이고, f(3.1415, true)는 기본 식 fArguments((...))가 붙은 형태예요. Point{1, 2}는 복합 리터럴(composite literal), m["foo"]는 인덱스, obj.color는 셀렉터가 붙은 기본 식이에요. 마지막의 f.p[i].x()처럼 기본 식에 여러 하위 구조가 연이어 붙는 것도 당연히 하나의 기본 식으로 취급돼요.

이 조각들이 각각 정확히 어떤 의미를 갖는지는 뒤에서 다룰 단항·이항 연산과 함께, 셀렉터·인덱스·슬라이스·타입 단언·호출 각각의 절에서 조금씩 더 자세히 살펴볼게요.

더 알아보기

  • Operand — 기본 식의 가장 원자적인 출발점이 되는 피연산자 규칙이에요.
  • Composite literalsPoint{1, 2}처럼 값을 나열해 구조체·배열·슬라이스·맵을 만드는 리터럴이에요. 여기서는 기본 식의 한 형태로 등장해요.
  • Selectors / Index expressions / Slice expressions / Type assertions / CallsPrimaryExpr 뒤에 붙는 다섯 가지 확장 구조 각각의 동작 방식이에요.