[Go] 명명 규칙
개요
Go는 간결하고 명확한 코드를 중요시하며, 명명 규칙은 코드의 가독성과 유지보수성에 큰 영향을 미칩니다. Go의 명명 규칙은 단순하지만 일관성 있게 적용해야 합니다.
Go의 명명 철학
- 간결함(Brevity): 짧지만 의미가 명확한 이름
- 일관성(Consistency): 전체 코드베이스에서 동일한 스타일
- 가독성(Readability): 읽기 쉽고 이해하기 쉬운 이름
- 컨텍스트(Context): 스코프에 따라 이름 길이 조정
패키지명 (Package Names)
규칙
- 소문자만 사용 (언더스코어, 하이픈 사용 금지)
- 단일 단어 선호 (짧고 간결하게)
- 명사형 사용 (동사 피하기)
- 복수형보다 단수형
- 축약어는 명확한 경우만
좋은 예
package fmt // formatting
package http // HTTP 관련
package json // JSON 처리
package time // 시간 관련
package io // I/O 작업
package sql // SQL 데이터베이스
package sync // 동기화
package bytes // 바이트 조작
나쁜 예
package fmt_util // ❌ 언더스코어 사용
package httpserver // ❌ 너무 구체적 (http만으로 충분)
package utils // ❌ 모호함 (무엇을 위한 유틸?)
package myPackage // ❌ 카멜케이스
package HTTP // ❌ 대문자
package helpers // ❌ 너무 일반적
패키지 사용 시 고려사항
패키지명은 변수명의 일부가 되므로 중복을 피해야 합니다.
// ✅ 좋은 예
http.Server // http 패키지의 Server
json.Encoder // json 패키지의 Encoder
time.Now() // time 패키지의 Now 함수
// ❌ 나쁜 예 (중복)
http.HTTPServer // http.Server로 충분
json.JSONEncoder // json.Encoder로 충분
변수명 (Variable Names)
기본 규칙
- 카멜케이스(camelCase) 사용
- 짧은 스코프에는 짧은 이름
- 긴 스코프에는 설명적인 이름
- 타입 정보 포함 가능 (필요시)
스코프에 따른 이름 길이
짧은 스코프 (함수 내, 반복문)
func calculateSum(numbers []int) int {
sum := 0
for _, n := range numbers { // n: 짧은 스코프
sum += n
}
return sum
}
// 일반적인 짧은 변수명
i, j, k // 인덱스
n // 숫자, 개수
s // 문자열
r // Reader
w // Writer
c // 채널, 문자
err // 에러
긴 스코프 (패키지 레벨, 구조체 필드)
package config
var (
MaxConnections int = 100
DefaultTimeout int = 30
DatabaseURL string = "localhost:5432"
EnableDebugLogging bool = false
)
type UserProfile struct {
UserID int64
EmailAddress string
DisplayName string
AccountStatus string
}
타입별 명명 패턴
불린 변수
is, has, can, should 등의 접두사 사용
isActive := true
hasPermission := false
canEdit := checkEditPermission()
shouldRetry := attempts < maxAttempts
슬라이스/배열
복수형 사용
users := []User{}
items := []Item{}
numbers := []int{1, 2, 3}
맵
복수형 또는 Map 접미사
usersByID := make(map[int64]*User)
configMap := make(map[string]string)
cache := make(map[string]interface{})
카운터/인덱스
count := 0
index := -1
currentIndex := 0
userCount := len(users)
함수명 (Function Names)
기본 규칙
- 카멜케이스(camelCase) 사용
- 동사로 시작 (액션 표현)
- 명확하고 설명적
패턴
Getter (Get 접두사 생략)
// ✅ 좋은 예
func (u *User) Name() string {
return u.name
}
func (u *User) Email() string {
return u.email
}
// ❌ 나쁜 예 - Get 불필요
func (u *User) GetName() string {
return u.name
}
Setter (Set 접두사 사용)
func (u *User) SetName(name string) {
u.name = name
}
func (u *User) SetEmail(email string) {
u.email = email
}
불린 반환 함수
func IsValid(s string) bool { /* ... */ }
func HasPrefix(s, prefix string) bool { /* ... */ }
func CanAccess(user User, resource Resource) bool { /* ... */ }
생성자
New 또는 New<Type> 사용
// 단일 타입 패키지
func New() *Server {
return &Server{}
}
// 여러 타입이 있는 패키지
func NewServer() *Server {
return &Server{}
}
func NewClient() *Client {
return &Client{}
}
변환 함수
func ToString(n int) string { /* ... */ }
func ToInt(s string) (int, error) { /* ... */ }
func ParseJSON(data []byte) (map[string]interface{}, error) { /* ... */ }
상수명 (Constant Names)
규칙
- 카멜케이스(CamelCase) 사용 (대문자로 시작 권장)
- 모두 대문자 + 언더스코어 사용 안 함 (Go 스타일 아님)
- 의미 명확하게
좋은 예
const (
MaxRetries = 3
DefaultTimeout = 30 * time.Second
StatusOK = 200
StatusNotFound = 404
BufferSize = 1024
)
const Pi = 3.14159
const Version = "1.0.0"
나쁜 예
const (
MAX_RETRIES = 3 // ❌ 언더스코어 사용
DEFAULT_TIME_OUT = 30 // ❌ 언더스코어 사용
status_ok = 200 // ❌ 소문자 시작
)
열거형 (iota 사용)
const (
StatusPending Status = iota // 0
StatusActive // 1
StatusInactive // 2
StatusDeleted // 3
)
const (
_ = iota // 0 무시
KB ByteSize = 1 << (10 * iota) // 1024
MB // 1048576
GB // 1073741824
)
타입명 (Type Names)
기본 규칙
- 카멜케이스(CamelCase) 사용 (대문자로 시작)
- 명사형 사용
- 짧고 명확하게
구조체
type User struct {
ID int64
Name string
}
type HTTPServer struct {
Address string
Port int
}
type RequestHandler struct {
// ...
}
타입 별칭
type UserID int64
type Email string
type Timestamp int64
type Handler func(http.ResponseWriter, *http.Request)
인터페이스명 (Interface Names)
규칙
- 단일 메서드 인터페이스: 메서드명 +
er접미사 - 다중 메서드 인터페이스: 설명적인 명사
단일 메서드 인터페이스
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
type Stringer interface {
String() string
}
type Handler interface {
Handle(ctx Context)
}
다중 메서드 인터페이스
type ReadWriter interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
}
type Database interface {
Connect() error
Execute(query string) error
Close() error
}
type Cache interface {
Get(key string) (interface{}, bool)
Set(key string, value interface{})
Delete(key string)
}
가시성 (Visibility)
공개 (Exported) - 대문자 시작
다른 패키지에서 접근 가능
package user
type User struct { // 공개 타입
ID int64 // 공개 필드
Name string // 공개 필드
age int // 비공개 필드
}
func NewUser() *User { // 공개 함수
return &User{}
}
func (u *User) GetAge() int { // 공개 메서드
return u.age
}
비공개 (Unexported) - 소문자 시작
같은 패키지 내에서만 접근 가능
package user
type userCache struct { // 비공개 타입
data map[int64]*User
}
func validateEmail(email string) bool { // 비공개 함수
// 이메일 검증 로직
return true
}
const maxAttempts = 3 // 비공개 상수
약어와 축약어 (Acronyms and Abbreviations)
규칙
- 잘 알려진 약어는 일관되게 대문자 사용
- 단, 비공개 변수는 소문자
일반적인 약어
// 공개 (Exported)
type HTTPServer struct{}
type URLPath struct{}
type JSONEncoder struct{}
type XMLParser struct{}
type IDGenerator struct{}
type APIClient struct{}
// 비공개 (Unexported)
var httpClient *http.Client
var urlPath string
var jsonData []byte
var apiKey string
약어 목록
HTTP, HTTPS, URL, URI, API, JSON, XML, HTML, CSS, SQL
ID, UUID, IP, TCP, UDP, DNS, SSH, FTP
DB, DAO, DTO, VO
CPU, RAM, GPU, USB, SSD
혼합 사용
// ✅ 좋은 예
type UserID int64
type HTTPSConnection struct{}
var userID int64 = 12345
// ❌ 나쁜 예
type UserId int64 // ID는 대문자로
type HttpsConnection struct{} // HTTPS로
에러 변수 (Error Variables)
규칙
Err접두사 사용- 설명적인 이름
var (
ErrNotFound = errors.New("not found")
ErrInvalidInput = errors.New("invalid input")
ErrUnauthorized = errors.New("unauthorized")
ErrTimeout = errors.New("timeout")
ErrConnectionClosed = errors.New("connection closed")
)
// 사용 예
if err == ErrNotFound {
// 처리
}
테스트 함수 (Test Functions)
규칙
Test접두사 + 테스트 대상 이름
package user
import "testing"
func TestUserCreation(t *testing.T) {
// 테스트 코드
}
func TestUserValidation(t *testing.T) {
// 테스트 코드
}
func BenchmarkUserCreation(b *testing.B) {
// 벤치마크 코드
}
func ExampleNewUser() {
// 예제 코드
}
좋은 예 vs 나쁜 예
변수명
// ✅ 좋은 예
var userCount int
var activeUsers []User
var isAuthenticated bool
var httpClient *http.Client
// ❌ 나쁜 예
var n int // 너무 모호
var user_count int // 언더스코어 사용
var IsAuthenticated bool // 공개 의도 아니면 소문자
var client *http.Client // 타입 정보 부족
함수명
// ✅ 좋은 예
func GetUser(id int64) (*User, error)
func CreateAccount(user User) error
func IsValid(email string) bool
func ParseJSON(data []byte) (map[string]interface{}, error)
// ❌ 나쁜 예
func get_user(id int64) (*User, error) // 언더스코어
func account_create(user User) error // 동사 위치
func CheckIsValid(email string) bool // Is로 충분
func JSON_Parse(data []byte) (map[string]interface{}, error) // 언더스코어
타입명
// ✅ 좋은 예
type UserProfile struct{}
type HTTPRequest struct{}
type JSONEncoder struct{}
// ❌ 나쁜 예
type userProfile struct{} // 공개하려면 대문자
type HttpRequest struct{} // HTTP로
type Json_Encoder struct{} // 언더스코어
특수 케이스
리시버 (Receiver) 이름
- 1-2글자 약어 사용 (타입명의 첫 글자)
- 일관성 유지
type User struct {
Name string
}
// ✅ 좋은 예
func (u *User) GetName() string {
return u.Name
}
func (u *User) SetName(name string) {
u.Name = name
}
// ❌ 나쁜 예
func (user *User) GetName() string { // 너무 길음
return user.Name
}
func (this *User) SetName(name string) { // this는 Go 스타일 아님
this.Name = name
}
파일명
- 소문자 + 언더스코어
- 패키지명과 일치 권장
user.go
user_test.go
http_client.go
json_parser.go
컨텍스트에 따른 이름
짧은 이름이 적절한 경우
// 반복문
for i := 0; i < len(items); i++ {}
for _, item := range items {}
// 짧은 함수
func add(a, b int) int {
return a + b
}
// 클로저
items := filter(users, func(u User) bool {
return u.Age > 18
})
긴 이름이 필요한 경우
// 패키지 레벨 변수
var DefaultDatabaseConnection *sql.DB
var MaximumConcurrentConnections = 100
// 공개 API
func CreateUserWithProfile(user User, profile Profile) error {
// ...
}
베스트 프랙티스
- 일관성이 가장 중요: 프로젝트 전체에서 동일한 스타일 유지
- gofmt 사용: 자동 포맷팅으로 일관성 보장
- golint 실행: 명명 규칙 자동 검사
- 문서화: 공개 API는 반드시 주석 추가
- 축약어 최소화: 명확한 경우에만 사용
- 타입 정보 중복 피하기:
userString대신userName - 컨텍스트 활용: 패키지명이 이미 제공하는 정보는 생략
- 동사 우선: 함수명은 액션을 표현
- Go 커뮤니티 관습 따르기: 표준 라이브러리 참고
도구
명명 규칙 검사 도구
# golint 설치 및 실행
go install golang.org/x/lint/golint@latest
golint ./...
# staticcheck 실행
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck ./...
# gofmt 검사
gofmt -l .