소개
이 문서에는 Go 가독성 멘토들의 제시한 조언에 대한 표준 가이드, 설명 및 예제를 통합 및 제공하기 위한 스타일 결정이 포함되어 있습니다.
이 문서는 완전한 것이 아니며 시간이 지남에 따라 계속해서 발전할 것입니다. 핵심 스타일 가이드와 여기에서 제공된 조언이 상충하는 경우 스타일 가이드가 우선하며 이 문서는 그에 맞게 업데이트되어야 합니다.
전체 Go 스타일 문서 세트는 개요를 참조하세요.
다음 섹션은 스타일 결정에서 스타일 가이드의 다른 부분으로 이동되었습니다:
MixedCaps: guide#mixed-caps 참조
Formatting: guide#formatting 참조
Line Length: guide#line-length 참조
네이밍
네이밍에 대한 개요는 핵심 스타일 가이드 내의 네이밍 섹션을 참조하십시오. 다음 섹션은 네이밍의 구체적인 영역에 대한 추가적인 설명을 제공합니다.
언더스코어
일반적으로 Go에서는 이름에 언더스코어를 포함하지 않아야 합니다. 이 원칙에는 세 가지 예외가 있습니다:
- 생성된 코드에서만 가져온 패키지 이름은 언더스코어를 포함할 수 있습니다. 다중 단어 패키지 이름 선택 방법에 대한 자세한 내용은 패키지 이름을 참조하세요.
- *_test.go 파일 내의 테스트, 벤치마크 및 예제 함수 이름에는 언더스코어를 포함할 수 있습니다.
- 운영 체제 또는 cgo와 상호 작용하는 저수준 라이브러리는 syscall에서처럼 식별자를 재사용할 수 있습니다. 대부분의 코드베이스에서는 매우 드물 것으로 예상됩니다.
패키지 이름
Go 패키지 이름은 짧아야 하며 소문자만을 포함해야 합니다. 여러 단어로 구성된 패키지 이름은 모두 소문자로 유지되어야 합니다. 예를 들어, 패키지 이름이 tabwriter인 경우에는 tabWriter, TabWriter 또는 tab_writer로 이름을 지정하지 않습니다.
일반적으로 일반적으로 사용되는 지역 변수 이름에 의해 가려질 가능성이 있는 패키지 이름을 선택하지 마십시오. 예를 들어, count보다는 usercount가 일반적으로 사용되는 변수 이름입니다.
Go 패키지 이름에는 언더스코어를 사용하지 않아야 합니다. 이름에 언더스코어가 포함된 패키지를 가져와야 하는 경우(일반적으로 생성된 코드나 서드파티 코드에서) Go 코드에서 사용하기에 적합한 이름으로 가져와야 합니다.
이에는 생성된 코드에서만 가져오는 패키지 이름에 언더스코어를 포함하는 경우가 있습니다. 구체적인 예시는 다음과 같습니다:
- 외부 테스트 패키지에 _test 접미사 사용, 예를 들어 통합 테스트
- 패키지 수준의 문서 예제에 _test 접미사 사용
util, utility, common, helper와 같은 의미가 없는 패키지 이름을 피하세요. “유틸리티 패키지”라고 불리는 것에 대해 더 알아보세요.
임포트된 패키지가 이름을 변경할 때 (예: import foopb “path/to/foo_go_proto”), 패키지의 로컬 이름은 파일에서 패키지의 심볼을 참조하는 방식을 지시하기 때문에 위의 규칙을 준수해야 합니다. 특히 동일한 또는 가까운 패키지에서 여러 파일에서 동일한 이름을 사용하여 일관성을 유지해야 합니다.
더 자세한 내용은 Go 블로그의 “패키지 이름에 관한” 게시물을 참조하세요.
Receiver names
리시버 변수 이름은 다음과 같아야 합니다:
- 짧아야 합니다 (보통 한 글자 또는 두 글자)
- 해당 타입을 대표하는 약어여야 합니다
- 해당 타입의 모든 리시버에 일관되게 적용되어야 합니다.
Long Name | Better Name |
---|---|
func (tray Tray) | func (t Tray) |
func (info *ResearchInfo) | func (ri *ResearchInfo) |
func (this *ReportWriter) | func (w *ReportWriter) |
func (self *Scanner) | func (s *Scanner) |
상수 이름
상수 이름은 Go 언어에서 다른 모든 이름과 마찬가지로 MixedCaps 형식을 사용해야 합니다. (Exported 상수는 대문자로 시작하고, unexported 상수는 소문자로 시작합니다.) 이는 다른 언어의 관례를 어길 때에도 적용됩니다. 상수 이름은 값의 파생물이 아니라 값이 무엇을 나타내는지 설명해야 합니다.
1
2
3
4
5
6
7
8
// Good:
const MaxPacketSize= 512
const (
ExecuteBit= 1<< iota
WriteBit
ReadBit
)
Non-MixedCaps 형식이나 K 접두사가 있는 상수 이름을 사용하지 마세요.
1
2
3
4
// Bad:
const MAX_PACKET_SIZE = 512
const kMaxBufferSize = 1024
const KMaxUsersPergroup = 500
상수 이름은 값을 기반으로 하는 것이 아니라 역할을 기반으로 지어야 합니다. 만약 상수가 값 외에 역할이 없다면, 그것을 상수로 정의하는 것은 불필요합니다.
1
2
3
4
5
6
7
// Bad:
const Twelve = 12
const (
UserNameColumn = "username"
GroupColumn = "group"
)
약어
이름에 포함된 약어나 머리글자로 된 단어들 (예: URL
과 NATO
)은 동일한 대소문자를 사용해야 합니다. URL
은 URL
이나 url
로 나타내야 합니다 (urlPony
또는 URLPony
처럼), Url
로는 사용하면 안 됩니다. 이는 “identifier”를 축약한 경우에도 ID
에 적용됩니다. appId
대신 appID
로 작성해야 합니다.
- 여러 개의 약어가 포함된 이름 (예:
XMLAPI
는XML
과API
를 포함하고 있음)의 경우, 각 약어의 각 글자는 동일한 대소문자를 가져야 하지만, 이름에 포함된 각 약어가 동일한 대소문자를 가져야 할 필요는 없습니다. - 소문자를 포함하는 약어가 있는 이름 (예:
DDoS
,iOS
,gRPC
)의 경우, 약어는 일반 문장에서와 같은 형태로 나타내야 합니다. 그러나 내보내기 가능성을 위해 첫 글자를 변경해야 할 경우, 전체 약어는 동일한 대소문자여야 합니다 (예:ddos
,IOS
,GRPC
).
Initialism(s) | Scope | Correct | Incorrect |
---|---|---|---|
XML API | Exported | XMLAPI | XmlApi, XMLApi, XmlAPI, XMLapi |
XML API | Unexported | xmlAPI | xmlapi, xmlApi |
iOS | Exported | IOS | Ios, IoS |
iOS | Unexported | iOS | ios |
gRPC | Exported | GRPC | Grpc |
gRPC | Unexported | gRPC | grpc |
DDoS | Exported | DDoS | DDOS, Ddos |
DDoS | Unexported | ddos | dDoS, dDOS |
게터(Getters)
함수와 메서드의 이름은 해당 개념이 “get”이라는 단어를 사용하는 경우 (예: HTTP GET)를 제외하고는 Get
또는 get
접두사를 사용해서는 안 됩니다. 대신 명사로 직접 이름을 시작하는 것이 좋습니다. 예를 들어 GetCounts
대신 Counts
를 사용하세요.
만약 함수가 복잡한 계산이나 원격 호출을 수행하는 경우, 함수 호출이 시간이 걸리거나 차단되거나 실패할 수 있음을 독자에게 명확히 알리기 위해 Get
대신 Compute
또는 Fetch
와 같은 다른 단어를 사용할 수 있습니다.
변수 이름
일반적인 원칙은 이름의 길이는 그 범위의 크기와 비례하며, 해당 범위 내에서 사용 횟수에 반비례해야 한다는 것입니다. 파일 범위에서 생성된 변수는 여러 단어를 필요로 할 수 있지만, 단일 내부 블록에 범위가 지정된 변수는 단어 하나 또는 문자 몇 개만으로 코드를 명확하게 유지하고 불필요한 정보를 피하기 위해 사용될 수 있습니다.
다음은 대략적인 기준입니다. 이러한 숫자적 가이드라인은 엄격한 규칙은 아닙니다. 맥락, 명확성, 그리고 간결성에 기반하여 판단을 적용하세요.
- 작은 범위는 한 두 가지 작은 작업(1-7줄 정도)이 수행되는 범위입니다.
- 중간 범위는 몇 가지 작은 작업 또는 한 가지 큰 작업(8-15줄 정도)이 수행되는 범위입니다.
- 큰 범위는 한 가지 또는 몇 가지 큰 작업(15-25줄 정도)이 수행되는 범위입니다.
- 매우 큰 범위는 한 페이지 이상(25줄 이상)을 포함하는 범위입니다.
작은 범위 내에서는 완전히 명확한 이름(예: 카운터용 c
)이 큰 범위에서는 부족할 수 있으며, 코드 내에서 목적을 독자에게 상기시키기 위해 명확성을 갖추도록 설명이 필요할 수 있습니다. 많은 변수가 있는 범위 또는 유사한 값이나 개념을 나타내는 변수는 범위가 제시하는 것보다 긴 변수 이름이 필요할 수 있습니다.
변수 이름의 명확성을 유지하기 위해 개념의 특정성도 도움이 될 수 있습니다. 예를 들어, 사용 중인 데이터베이스가 하나뿐이라고 가정할 경우, 범위가 매우 크더라도 보통 작은 범위에 예약되는 것으로 예상되는 db
와 같은 짧은 변수 이름은 여전히 완전히 명확할 수 있습니다. 이 경우, database
라는 단일 단어가 범위의 크기를 기준으로 수용 가능하겠지만, db
는 해당 단어를 짧게 줄인 매우 일반적인 표현이므로 필수적이지는 않습니다.
로컬 변수의 이름은 값을 생성한 위치보다는 현재 컨텍스트에서 변수가 담고 있는 내용과 사용 방식을 반영해야 합니다. 예를 들어, 보통은 최적의 로컬 변수 이름이 구조체나 프로토콜 버퍼 필드 이름과 같지 않습니다.
일반적으로 다음을 따릅니다:
count
나options
와 같은 단일 단어 이름은 좋은 시작점입니다.- 유사한 이름을 구분하기 위해 추가적인 단어를 추가할 수 있습니다. 예를 들어
userCount
와projectCount
와 같은 이름을 사용합니다. - 타이핑을 절약하기 위해 문자를 단순히 생략하지 마세요. 예를 들어, 특히 내보낸 이름의 경우
Sbx
보다는Sandbox
가 선호됩니다. - 대부분의 변수 이름에서 유형 및 유형과 유사한 단어는 생략합니다.
- 숫자의 경우,
numUsers
나usersInt
보다userCount
가 더 좋은 이름입니다. - 슬라이스의 경우,
userSlice
보다users
가 더 좋은 이름입니다. - 범위 내에서 두 개의 값이 있는 경우 유형과 유사한 한정자를 포함할 수 있으며, 예를 들어 입력이
ageString
에 저장되어 있고 구문 분석된 값을age
에 사용하는 경우ageString
을 저장하는 데 사용합니다.
- 숫자의 경우,
- 주변 문맥에서 명확한 단어를 생략합니다. 예를 들어,
UserCount
메서드의 구현에서userCount
라는 로컬 변수는 중복일 수 있으며,count
,users
또는 심지어c
와 같이 읽기 쉬운 변수로 대체할 수 있습니다.
한 글자 변수 이름
한 글자 변수 이름은 반복을 최소화하기 위한 유용한 도구가 될 수 있지만, 코드를 불필요하게 알기 어렵게 만들 수도 있습니다. 한 글자 변수가 전체 단어와 비슷하고, 한 글자 변수 대신에 나타나는 것이 반복적일 경우에만 사용하세요.
일반적으로 다음을 따릅니다:
- 메서드 리시버 변수의 경우, 한 글자 또는 두 글자 이름이 선호됩니다.
- 일반적인 타입에 익숙한 변수 이름을 사용하는 것이 도움이 됩니다:
io.Reader
나http.Request
의 경우r
을 사용합니다.io.Writer
나http.ResponseWriter
의 경우w
를 사용합니다.
- 한 글자 식별자는 정수 루프 변수에 적합하며, 특히 인덱스(
i
)나 좌표(x
와y
)에 사용됩니다. - 범위가 짧은 경우에는 약어를 사용할 수도 있습니다. 예를 들어
for _, n := range nodes { ... }
와 같이 사용할 수 있습니다.