Go 코딩 컨벤션

1 개요[ | ]

Go 코딩 컨벤션

2 Effective Go[ | ]

아파치 라이선스 2.0[1]

2.1 Getter[ | ]

Go는 getters와 setters를 자체적으로 제공하지 않는다. 스스로 getters와 setters를 만들어 사용하면 되는데 이는 전혀 문제될게 없으며 이는 적절하고 일반적인 방법이다. 그러나 getter의 이름에 Get을 넣는건 Go언어 답지도, 필수적이지도 않다. 만약 owner(첫 문자가 소문자이며 패키지 밖으로 노출되지 않는다.)라는 필드를 가지고 있다면 getter 메서드는 GetOwner가 아닌 Owner(첫 문자가 대문자이며, 패키지 밖으로 노출됨)라고 불러야한다. 패키지밖으로 노출하기 위해 대문자 이름을 사용하는 것은 메서드로부터 필드를 식별할 수 있는 훅(hook)을 제공한다. 만약 필요하다면, setter 함수는 SetOwner라고 불릴 것이다. 두 이름 모두 읽기 쉽다.

3 Go 스타일가이드[ | ]

언라이선스[2]

3.1 오류에 컨텍스트 추가[ | ]

Don't Do
file, err := os.Open("foo.txt")
if err != nil {
	return err
}

위의 접근 방식을 사용하면 컨텍스트 누락으로 인해 불명확한 오류 메시지가 나타날 수 있다.

file, err := os.Open("foo.txt")
if err != nil {
	return fmt.Errorf("open foo.txt failed: %w", err)
}

사용자 지정 메시지로 오류를 래핑하면 스택으로 전파될 때 컨텍스트를 제공한다. 이것이 항상 합리적인 것 아니다. 반환된 오류의 컨텍스트가 충분한지 확신이 없다면 이를 래핑하자.

3.2 의존성 관리[ | ]

모듈 사용

모듈을 사용하자. 내장된 go 종속성 관리 도구이고 널리 지원된다(Go 1.11+에서 사용 가능).

시맨틱 버전 관리 사용

시맨틱 버전 관리를 사용하여 패키지에 태그를 지정한다. 릴리스와 관련된 모범사례에 대해서는 모듈 위키를 참고하자. go 패키지의 git 태그는 v<major>.<minor>.<patch> 형식이어야 한다(예: v1.0.1).

3.3 전역변수 사용 자제[ | ]

Don't Do
var db *sql.DB

func main() {
	db = // ...
	http.HandleFunc("/drop", DropHandler)
	// ...
}

func DropHandler(w http.ResponseWriter, r *http.Request) {
	db.Exec("DROP DATABASE prod")
}
func main() {
	db := // ...
	handlers := Handlers{DB: db}
	http.HandleFunc("/drop", handlers.DropHandler)
	// ...
}

type Handlers struct {
	DB *sql.DB
}

func (h *Handlers) DropHandler(w http.ResponseWriter, r *http.Request) {
	h.DB.Exec("DROP DATABASE prod")
}
전역변수는 테스트와 읽기를 어렵게 만들고, 모든 메소드에서 (필요하지 않은 경우에도) 접근할 수 있게 된다. 구조체를 사용하여 변수를 캡슐화하고 해당 구조체에 대해 구현된 메소드를 만들어 실제로 필요한 함수에서만 사용할 수 있도록 한다.

또는 대안으로, 고차 함수를 사용하여 클로저를 통해 종속성을 주입할 수 있다.

func main() {
	db := // ...
	http.HandleFunc("/drop", DropHandler(db))
	// ...
}

func DropHandler(db *sql.DB) http.HandleFunc {
	return func (w http.ResponseWriter, r *http.Request) {
		db.Exec("DROP DATABASE prod")
	}
}

전역변수나 상수가 꼭 필요한 경우(예: 오류 또는 문자열 상수를 정의하기 위해), 파일의 맨 위에 두자.

Don't Do
import "xyz"

func someFunc() {
	//...
}

const route = "/some-route"

func someOtherFunc() {
	// usage of route
}

var NotFoundErr = errors.New("not found")

func yetAnotherFunc() {
	// usage of NotFoundErr
}
import "xyz"

const route = "/some-route"

var NotFoundErr = errors.New("not found")

func someFunc() {
	//...
}

func someOtherFunc() {
	// usage of route
}

func yetAnotherFunc() {
	// usage of NotFoundErr
}

4 같이 보기[ | ]

5 참고[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}