본문 바로가기
Programming/GO

Effective Go에 대해 - 1

by 코인선물로부자된다 2023. 1. 2.
반응형

https://go.dev/doc/effective_go

[Effective Go - The Go Programming Language

Documentation Effective Go Effective Go Introduction Go is a new language. Although it borrows ideas from existing languages, it has unusual properties that make effective Go programs different in character from programs written in its relatives. A straigh

go.dev](https://go.dev/doc/effective_go)

Formatting

안좋은 예
type T struct {
name string // name of the object
value int // its value
}

좋은 예 (들여 쓰기, 주석 줄 맞춤)
type T struct {
name string // name of the object
value int // its value
}

Commentary

  1. 최상위 선언 앞에 주석은 선언 자체를 문서화하는 의미
  2. Go Pakcage 명령에 대한 기본 문서

Package names

패키지 임포터는 간결하게 소문자, 단일 단어로 이루어지도록 구성
import 시, 패키지의 디렉토리를 모두 포함
좋은 예
import encoding/base64

안좋은 예
import encodingBase64
import encoding_64

Getter

특정 객체 getter, setter 설정 시, 특정 규칙을 따라야 함
getter method에 굳이 get 붙일 필요없다.

안좋은 예
onwer := obj.getOwner()

좋은 예
onwer := obj.Owner()
if owner != user {
obj.setOwner(user)
}

Interface names

단일, 다중 메서드 인터페이스 : Reader, Writer, -er

MixedCaps

Camel Case (maxLength) > Snake Case (max_length)
Camel Case 사용

Semicolons

int, float64, string constant 등에는 기본으로 ; 이 들어가나 표현하지는 않는다.
주의점은 제어 구조(for, switch, select)의 중괄호는 다음 줄에 놓지 못한다.
if i < f() ;
{

}
위의 구조처럼 되기 때문이다.

Control Structures

If

If 뒤의 구문에 else 는 생략된 것으로 보기때문에 가독성이 좋은 코드를 위해선 에러에 대한 명시를 해주고 뒷처리를 생략하는 것이 좋은 방법이다.
오류 처리를 명시적으로 진행해주기 때문에 가독성이 좋다고 볼 수 있다.

f, err := os.Open(name)
if err != nil {
return err
}
d, err := f.Stat()
if err != nil {
f.Close()
return err
}
codeUsing(f, d)

Redeclaration and reassignment

f, err := os.Open(name)
d, err := f.Stat()
함수 본문과 괄호의 순위가 동등한 상태에서 재할당은 크게 문제 되지 않는다.

For

sum := 0
for i :=0; i < 10; i++ {
sum += i
}

for key := range m {
if key.expired() {
delete(m, key)
}
}

_ 를 이용하여 값을 버림
sum := 0
for _, value := range array {
sum += value
}

쉼표 연산자는 없고 ++, -- 는 명령문

Switch

표현식은 상수, 정수일필요없으며 표현식에 일치하는 항목 발견될때까지 이동
쉼표로 구분된 목록 나열 가능
Switch는 C와 비슷하다.
break, continue 가능

Type Switch

var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}

Functions

Multiple return values
여러 반환 값이 가능하다.
byte, int := nextInt(b, i)
func nextInt(b []byte, i int) (int, int) { return i, i }

Named result parameters

매개변수를 일반 변수로 초기화하고 리턴 할 수 있음

Defer

Return 바로 전에 실행되도록 함수 호출을 예약
Defer는 런타임 패닉이 발생해도 실행되는 특징이 있고,
여러번 지정이 가능하며 기존의 함수호출 처럼 stack에 저장해 LIFO로 호출

func Contents(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close()
// 이후 return 실행 시, f.Close() 실행
return "A", err
}