왜 Go를 쓰는가
Go를 최신 문법 기능보다 배포 단순성, 빠른 컴파일, 표준 도구 체인, 동시성 모델 관점에서 어떻게 읽어야 하는지 정리합니다.
package main
import "fmt"
func main() {
fmt.Println("hello, go")
}Category
Preparing references and filters for this topic. 이 주제의 레퍼런스와 필터를 준비하고 있습니다.
Category Reference
모듈, 패키지, 함수, 다중 반환, defer, struct, interface, error, goroutine, channel, context까지 Go의 핵심 흐름을 카드형 레퍼런스로 정리합니다.
Search titles, summaries, tags, and subcategories.
Showing 29 cards.
Subcategory
4 cards
Go를 최신 문법 기능보다 배포 단순성, 빠른 컴파일, 표준 도구 체인, 동시성 모델 관점에서 어떻게 읽어야 하는지 정리합니다.
package main
import "fmt"
func main() {
fmt.Println("hello, go")
}`go mod init`부터 패키지 경계, `cmd/`와 `internal/` 같은 디렉터리 감각까지 Go 프로젝트를 어떻게 시작하면 좋은지 정리합니다.
mkdir myapp
cd myapp
go mod init example.com/myappGo에서 package가 디렉터리와 어떻게 연결되고, import 경로와 대문자 공개 규칙을 어떻게 읽어야 하는지 정리합니다.
package user
import "time"
type Profile struct {
ID string
createdAt time.Time
}`go.mod`, `go.work`, `replace`가 각각 어떤 의존성 경계와 로컬 개발 흐름을 담당하는지 정리합니다.
module example.com/myapp
go 1.26
require github.com/google/uuid v1.6.07 cards
`var`, `:=`, `const`, zero value를 어떤 형태로 쓰고, 선언 위치와 타입 추론을 어떻게 읽어야 하는지 정리합니다.
var name string
count := 3
const maxRetries = 5Go의 `if`, `for`, `range`, `switch`가 어떤 형태를 갖고, 반복과 분기를 어떤 기준으로 고르는지 정리합니다.
if err != nil {
return err
}
for i := 0; i < len(items); i++ {
fmt.Println(items[i])
}
for _, item := range items {
fmt.Println(item)
}
switch status {
case http.StatusOK:
return nil
default:
return fmt.Errorf("bad status: %d", status)
}Go 함수 시그니처의 주요 형태, 다중 반환으로 값과 error를 함께 돌려주는 패턴, `defer`의 실행 시점을 정리합니다.
func ping() {}
func add(a int, b int) int {
return a + b
}
func readUser(id string) (User, error) {
// ...
}Go에서 데이터를 `struct`로 묶고, 동작을 method로 붙이고, 계약은 암시적 interface로 읽는 기본 흐름을 정리합니다.
type User struct {
Name string
Age int
}
func (u User) IsAdult() bool {
return u.Age >= 20
}`&`, `*`, value copy, pointer receiver를 어떻게 읽고, 값 전달과 포인터 전달을 어떤 기준으로 고르는지 정리합니다.
count := 3
ptr := &count
*ptr = 4
fmt.Println(count) // 4Go에서 slice와 map을 어떻게 만들고, nil과 empty의 차이를 어떻게 읽으며, `make`가 언제 필요한지 정리합니다.
names := []string{"Mina", "Jin"}
names = append(names, "Noah")
scores := map[string]int{"Mina": 10}
scores["Jin"] = 8
buf := make([]byte, 0, 1024)
seen := make(map[string]bool)Go 제네릭의 타입 매개변수, constraint, zero value 반환, generic type을 언제 쓰고 언제 피해야 하는지 정리합니다.
func First[T any](items []T) (T, bool) {
if len(items) == 0 {
var zero T
return zero, false
}
return items[0], true
}2 cards
Go에서 예외 대신 `error`를 어떻게 반환하는지, `%w`와 `errors.Is`/`errors.As`로 에러 문맥을 어떻게 보존하는지 정리합니다.
user, err := repo.Find(id)
if err != nil {
return fmt.Errorf("load user %s: %w", id, err)
}`go test`의 기본 흐름, `testing.T` 사용법, Go에서 자주 쓰는 table-driven test 패턴을 정리합니다.
go test ./...4 cards
Go 동시성을 시작할 때 goroutine 생성, channel 통신, `context` 취소 전파를 한 흐름으로 어떻게 묶어 읽어야 하는지 정리합니다.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ch := make(chan int)
go worker(ctx, ch)`sync.WaitGroup`, `Mutex`, `RWMutex`, `atomic`을 언제 쓰고, goroutine 종료와 공유 상태 보호를 어떻게 나눠야 하는지 정리합니다.
var wg sync.WaitGroup
for _, job := range jobs {
wg.Add(1)
go func(job Job) {
defer wg.Done()
process(job)
}(job)
}
wg.Wait()Go에서 worker pool과 pipeline을 언제 쓰는지, channel close, `WaitGroup`, context 취소를 어떻게 같이 설계해야 하는지 정리합니다.
jobs := make(chan Job)
results := make(chan Result)
for i := 0; i < workers; i++ {
go worker(ctx, jobs, results)
}`time.Sleep`, `Timer`, `Ticker`, timeout context를 언제 고르고, 반복 작업과 대기 흐름에서 어떤 정리 코드를 챙겨야 하는지 정리합니다.
time.Sleep(500 * time.Millisecond)
timer := time.NewTimer(2 * time.Second)
defer timer.Stop()
ticker := time.NewTicker(time.Second)
defer ticker.Stop()4 cards
`encoding/json`에서 exported field, struct tag, `omitempty`, `Marshal`/`Unmarshal`의 경계를 어떻게 읽어야 하는지 정리합니다.
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"`
}`os`, `io`, `bufio`, `embed`를 언제 쓰고, 파일을 읽고 쓰는 코드에서 close와 경로 경계를 어떻게 잡아야 하는지 정리합니다.
data, err := os.ReadFile("config.json")
if err != nil {
return err
}
if err := os.WriteFile("out.txt", data, 0o644); err != nil {
return err
}`database/sql`에서 `sql.Open`, connection pool, context가 붙은 query, rows close를 어떤 기준으로 읽어야 하는지 정리합니다.
db, err := sql.Open("postgres", dsn)
if err != nil {
return err
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
row := db.QueryRowContext(ctx, "select name from users where id = $1", id)`database/sql`에서 `BeginTx`, `Commit`, `Rollback`을 어떤 흐름으로 묶고, transaction 안에서 query를 어디에 붙여야 하는지 정리합니다.
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
if _, err := tx.ExecContext(ctx, query, args...); err != nil {
return err
}
return tx.Commit()2 cards
`net/http`의 `Handler`, `HandlerFunc`, `ServeMux`를 어떻게 읽고, middleware를 어떤 함수 조합으로 설계하는지 정리합니다.
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
http.ListenAndServe(":8080", mux)`http.Client`, request context, response body close, timeout 계층을 어떻게 나눠서 설계해야 하는지 정리합니다.
client := &http.Client{
Timeout: 5 * time.Second,
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return err
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()6 cards
`log`와 `log/slog`의 차이, 구조화 로그의 key-value 형태, handler와 context 로그를 어떤 기준으로 잡아야 하는지 정리합니다.
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info(
"request completed",
"method", r.Method,
"path", r.URL.Path,
"status", http.StatusOK,
)`os.Getenv`, `os.LookupEnv`, 문자열 파싱, 설정 struct를 어떻게 조합해 실행 환경별 설정을 읽는지 정리합니다.
port, ok := os.LookupEnv("PORT")
if !ok {
port = "8080"
}
debug, err := strconv.ParseBool(os.Getenv("DEBUG"))
if err != nil {
debug = false
}표준 `flag` 패키지로 옵션을 읽고, `FlagSet`으로 subcommand를 나누는 기본 구조를 정리합니다.
mytool serve -port 8080 -debug
mytool migrate -dry-run`go test -bench`, benchmark 함수, `pprof` 프로파일을 어떻게 읽고 성능 문제를 추적하는지 정리합니다.
go test -bench=. -benchmem ./...
go test -bench=BenchmarkEncode -cpuprofile cpu.out
go tool pprof cpu.out`go build`, `GOOS`, `GOARCH`, `CGO_ENABLED`를 어떻게 조합해 실행 파일을 만들고, cross compile에서 어디를 주의해야 하는지 정리합니다.
go build ./cmd/api
GOOS=linux GOARCH=amd64 go build -o bin/api-linux-amd64 ./cmd/api
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/api ./cmd/api`go test -race`로 data race를 어떻게 찾고, 공유 상태를 channel, mutex, atomic 중 무엇으로 보호해야 하는지 정리합니다.
go test -race ./...
go test -race ./internal/service
go run -race ./cmd/api