본문 바로가기
golang

Go google style guide - overview & guide

by marble25 2023. 11. 19.

Golang의 google style guide 문서를 번역해 보았다. 아무래도 Golang 언어를 만든 기업이니 google guide를 따르는게 좋지 않을까 하는 판단에서 uber guide 등 다른 가이드보다 구글 가이드를 참고하고자 한다.

참고 문서: https://google.github.io/styleguide/go/index

About

Go style guide는 readable하고 idiomatic한 go를 작성하는 가장 좋은 접근법을 작성해 두었다.

Document 대상 Normative Canonical

Style Guide 모두 Yes Yes
Style Decisions 가독성 멘토 Yes No
Best Practices 관심있는 모두 No No

 

정의

  • Canonical: 모든 코드가 지켜야 하는 것을 의미한다.
  • Normative: 잘 변하지 않는 것을 의미한다.
  • Idiomatic: 흔하고 유명하다.

Principles

Clarity

독자에게 읽기 쉬워야 한다. 이는 효과적인 이름 짓기, 유용한 주석, 효과적인 코드 구조를 통해 이뤄진다. 읽기 쉬운 코드가 쓰기 쉬운 코드보다 좋다.

코드는 무엇을 하는가?

Go는 코드가 무엇을 하는지 알기 쉽게 디자인되었다. 독자가 선행 지식을 필요로 한다면, 차라리 코드를 작성할 때 미래의 독자들에게 코드의 목적이 무엇인지 알려주는 편이 낫다.

코드가 무엇을 하는지 왜 알려줘야 하는가?

코드의 의미는 변수, 함수, 메소드, 패키지 이름으로 전달될 수 있다. 아닌 경우에는 주석을 달자. 읽는 사람이 익숙하지 않은 뉘앙스를 포함한다면, “Why?”는 굉장히 중요하다. 주석은 코드가 무엇을 하는지가 아닌, 왜 해야 하는지 알려주는 것이 좋다.

Simplicity

Go 코드는 쉽게 사용하고, 쉽게 읽히고, 쉽게 유지보수할 수 있어야 한다. 간단한 코드는:

  • Top to bottom으로 읽혀야 한다.
  • 뭘 하고 있는지 알고 있다 가정하지 않아야 한다.
  • 이전 코드를 모두 기억하고 있다고 가정하지 않아야 한다.
  • 불필요한 추상화를 하지 않아야 한다.
  • 불필요하게 특이한 이름을 짓지 않아야 한다.
  • value 전파가 명확해야 한다.
  • 왜 코드가 필요한지 주석이 있어야 한다.
  • documentation이 있어야 한다.
  • 유용한 에러와 유용한 test failure가 있어야 한다.

code simplicity와 API user simplicity 사이에 tradeoff가 발생할 수 있다. 때로는 end user가 사용하기 쉬울 수 있고, 때로는 end user가 api를 호출하기 위해 해야 하는 작업이 많을 수 있다. 이럴 때에는 코드 simplicity를 우선시하자.

같은 아이디어를 표현할 여러 방법이 있다면, 더 표준화된 툴을 사용하자.

  1. core language 구조를 사용하자(channel, slice, map, loop, struct)
  2. 아니면, standard library를 찾아보자(HTTP client, template engine 등)
  3. 새로 만들기 전에 Google codebase의 core library를 찾아보자.

예를 들어, 집합에 속해있는지 체크하기 위해서, map[string]bool 정도면 충분하다. Set-type을 가지는 라이브러리 사용은 map으로 안될 때에 고려해 보자.

Concision

코드의 의미가 명확해야 한다. 특히, 반복적인 코드에서 살짝만 변화가 있는 경우 독자가 변화를 감지하기 어렵게 된다. 코드를 구조화할 때 의미가 더 명확하게 드러나는 방법을 추구해야 한다.

관용적인 코드 구조를 이해하고 사용하는 것도 중요하다. 예를 들어, 다음 구문은 error handling에서 자주 사용되어 독자가 쉽게 목적을 이해할 수 있다.

// Good:
if err := doSomething(); err != nil {
    // ...
}

여기와 비슷해 보이지만 약간 다르다면 독자는 변화를 감지하지 못할 수 있다. 이 때는 “boosting signal”을 주는 것이 좋다.

// Good:
if err := doSomething(); err == nil { // if NO error
    // ...
}

Maintainability

코드는 작성된 후 여러번 수정된다. 읽기 쉬운 코드는 이해도 쉬울 뿐 아니라 쉽게 고칠 수 있게 한다.

Interface나 Type으로 추상화를 한다면, 충분한 장점을 제공하는 것을 보장해야 한다. Concrete type을 사용한다면 Editor나 IDE에서 직접적으로 연결되어 관련된 documentation을 볼 수 있지만, interface의 경우에는 정의만 볼 수 있다. Interface는 강력한 툴이지만, 비용이 발생한다.

유지가능한 코드는 간과하기 쉬운 중요한 디테일을 숨기지 말아야 한다.

// Bad:
// The use of = instead of := can change this line completely.
if user, err = db.UserByID(userID); err != nil {
    // ...
}
// Bad:
// The ! in the middle of this line is very easy to miss.
leap := (year%4 == 0) && (!(year%100 == 0) || (year%400 == 0))
// Good:u, err:= db.UserByID(userID)
if err!= nil {
return fmt.Errorf("invalid origin user: %s", err)
}
user= u
// Good:// Gregorian leap years aren't just year%4 == 0.// See <https://en.wikipedia.org/wiki/Leap_year#Algorithm.var> (
    leap4= year%4== 0
    leap100= year%100== 0
    leap400= year%400== 0
)
leap:= leap4&& (!leap100|| leap400)

유지 가능한 코드는 예측 가능한 이름을 사용해야 한다. 유지가능한 코드는 dependency를 최소화해야 한다.

Consistency

기존 코드베이스와 비슷하게 생겨야 하고 비슷하게 동작해야 한다. 일관성 규칙은 위의 어떤 규칙보다 우선하지는 않지만, 규칙이 충돌한다면 일관성을 지키는 것이 나을 수 있다.

Core guidelines

Formatting

gofmt tool의 output에 맞게 작성해야 한다.

MixedCaps

MixedCaps나 mixedCaps는 괜찮지만, MAX_LENGTH나 max_length는 좋지 않다. Underscore를 사용하지 말자.

Line length

Go에는 정해진 line length가 없다. 너무 길다면, refactoring하자. 이미 실용적인 수준이라면, 줄을 길게 유지하자.

Naming

이름짓기는 예술의 영역이다. Go는 다른 language보다 이름을 짧게 짓는것을 선호하긴 하지만, 비슷한 가이드라인이 적용된다.

이름은:

  • 어디서 사용되는지에 대해 반복적으로 설명하지 말아야 한다.
  • 문맥을 고려하자.
  • 명확한 개념을 반복하지 말자.

Local consistency

가까운 곳에 위치한 코드끼리는 비슷하게 작성되어야 한다. (주로 같은 파일이나 패키지, 때로는 team이나 project directory) 예를 들면, 에러 출력시 %s를 사용할지 %v를 사용할지나 mutex 대신에 buffered channel을 사용할지 같은 것이 있다.

'golang' 카테고리의 다른 글

[TIL] golang buffer 복사  (1) 2023.12.21
Go google style guides - decisions  (0) 2023.12.09
Go garbage collection  (1) 2023.10.30
[TIL] Go buffer read  (0) 2023.10.27
Go convention 정리  (0) 2023.10.03