고 중급 #7 표준 라이브러리 투어
Go의 큰 강점 중 하나는 두꺼운 표준 라이브러리 입니다. 옛 자바스크립트가 작은 표준에 라이브러리로 채우는 모델이라면 — Go는 처음부터 풍부합니다. 이번 글은 자주 쓰이는 것들을 한 번에 훑습니다.
이 글은 깊이보다 — “이 용도에 이 패키지가 있다” 는 인덱스에 가깝습니다. 자세한 사용법은 각 패키지의 공식 문서가 가장 좋습니다.
fmt — 포맷팅 입출력
#
이미 기초 #2에서 다뤘지만 다시.
fmt.Println("hi") // 줄바꿈 자동
fmt.Print("줄바꿈 없음")
fmt.Printf("%s = %d\n", "n", 42)
s := fmt.Sprintf("v=%v", x) // 문자열로
fmt.Errorf("실패: %w", err) // 에러 만들기
// 자주 쓰는 verb
// %v 기본
// %+v 필드 이름 포함
// %#v Go 문법으로
// %d %s %t %f %T %qstrings — 문자열 도구
#
strings.Contains("hello", "ell") // true
strings.HasPrefix("hello", "he") // true
strings.HasSuffix("hello", "lo") // true
strings.Index("hello", "ll") // 2
strings.Replace("hello", "l", "L", -1) // heLLo (-1은 모두)
strings.ReplaceAll("hello", "l", "L") // heLLo
strings.ToUpper("hello") // HELLO
strings.ToLower("HELLO") // hello
strings.TrimSpace(" hello ") // "hello"
strings.Trim("---hi---", "-") // hi
strings.Split("a,b,c", ",") // ["a", "b", "c"]
strings.Join([]string{"a", "b"}, ",") // a,b
strings.Repeat("ab", 3) // ababab
strings.Fields(" a b c ") // ["a", "b", "c"]strings.Builder — 효율적 문자열 합성
#
var b strings.Builder
b.WriteString("Hello, ")
b.WriteString("World")
result := b.String() // "Hello, World"루프 안에서 s += other로 문자열을 합치면 — 매번 새 메모리 할당이 일어납니다. Builder는 내부 버퍼를 재사용해서 훨씬 효율적입니다.
strconv — 문자열 ↔ 숫자
#
strconv.Itoa(42) // "42"
strconv.Atoi("42") // (42, nil)
strconv.ParseInt("42", 10, 64) // (42, nil) — 진법, 비트 너비
strconv.ParseFloat("3.14", 64)
strconv.FormatFloat(3.14, 'f', 2, 64) // "3.14"
strconv.Quote("hi\n") // "\"hi\\n\""대부분의 경우에는 Itoa / Atoi / ParseFloat만 익혀도 충분합니다.
bytes — []byte도구
#
strings의 byte 슬라이스 버전. API가 거의 평행하게 만들어졌습니다.
bytes.Contains([]byte("hello"), []byte("ll"))
bytes.Equal(a, b)
bytes.Replace(...)
// Buffer — 가변 byte 버퍼
var buf bytes.Buffer
buf.WriteString("hi")
buf.Write([]byte("!"))
fmt.Println(buf.String())bytes.Buffer는 io.Reader/io.Writer를 모두 만족 — IO에서 메모리로 읽거나 쓸 때 자주 등장.
io — IO 인터페이스
#
#1 인터페이스에서 본 핵심 인터페이스들.
type Reader interface { Read(p []byte) (int, error) }
type Writer interface { Write(p []byte) (int, error) }
type Closer interface { Close() error }
io.ReadAll(r) // 전체 읽어 []byte
io.Copy(dst, src) // src → dst 복사
io.EOF // 읽기 끝 sentineldata, err := io.ReadAll(resp.Body)
defer resp.Body.Close()os — OS 자원
#
os.Args // 명령줄 인자
os.Getenv("HOME")
os.Setenv("KEY", "value")
os.Exit(1) // 프로그램 종료
os.Stdin / os.Stdout / os.Stderr // io.Reader/Writer
// 파일
file, err := os.Open("file.txt") // 읽기
file, err := os.Create("file.txt") // 쓰기 (덮어쓰기)
defer file.Close()
data, err := os.ReadFile("file.txt") // 한 번에 모두 읽기
err := os.WriteFile("file.txt", data, 0644)
// 디렉토리
entries, err := os.ReadDir("./")
os.MkdirAll("a/b/c", 0755)
os.Remove("file.txt")
os.RemoveAll("dir")path/filepath — 경로 다루기
#
filepath.Join("a", "b", "c") // a/b/c (OS에 맞게)
filepath.Base("/a/b/c.go") // c.go
filepath.Dir("/a/b/c.go") // /a/b
filepath.Ext("c.go") // .go
filepath.Abs("./file") // 절대 경로OS 별 구분자(Linux의 /, Windows의 \) 차이를 자동 처리.
time — 시간
#
now := time.Now()
yesterday := now.Add(-24 * time.Hour)
nextHour := now.Add(time.Hour)
// 차이
elapsed := time.Since(start) // 경과 시간
duration := time.Until(deadline) // 남은 시간
// 비교
now.After(other)
now.Before(other)
now.Equal(other)Duration #
time.Second
time.Minute
time.Hour
time.Millisecond
time.Microsecond
time.Nanosecond
3 * time.Second // 3초
500 * time.Millisecond // 0.5초포맷팅 — Go의 독특한 방식 #
now := time.Now()
fmt.Println(now.Format("2006-01-02 15:04:05"))
// Go가 정한 참조 시간
// 2006-01-02 15:04:05.999999999 -0700 MST = Mon Jan 2 15:04:05 MST 2006
// 즉 1 2 3 4 5 6 7다른 언어(YYYY-MM-DD)와 달리 — 특정 참조 시간(2006-01-02 15:04:05)을 적어 포맷을 표현합니다. 처음엔 어색하지만 익숙해지면 직관적입니다.
자주 쓰는 상수들:
time.RFC3339 // "2006-01-02T15:04:05Z07:00"
time.RFC1123
time.DateOnly // "2006-01-02"
time.TimeOnly // "15:04:05"Parse #
t, err := time.Parse(time.RFC3339, "2026-05-04T10:00:00Z")encoding/json — JSON
#
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
// 직렬화
data, err := json.Marshal(user)
data, err := json.MarshalIndent(user, "", " ") // 보기 좋게
// 역직렬화
var u User
err := json.Unmarshal(data, &u)
// 스트림
encoder := json.NewEncoder(os.Stdout)
encoder.Encode(user)
decoder := json.NewDecoder(file)
err := decoder.Decode(&u)json: 태그가 #6 구조체에서 본 부분입니다. omitempty는 zero value 면 결과에서 빼라는 뜻.
동적 JSON — map[string]any
#
스키마를 모르는 JSON을 다룰 때.
var data map[string]any
json.Unmarshal(rawJSON, &data)
if name, ok := data["name"].(string); ok {
fmt.Println(name)
}매번 타입 단언이 필요해 다소 번거롭습니다. 가능하면 struct 정의가 더 깔끔합니다.
sort — 정렬
#
sort.Ints(nums)
sort.Strings(names)
sort.Float64s(values)
// 슬라이스 정렬 — 함수로
sort.Slice(users, func(i, j int) bool {
return users[i].Age < users[j].Age
})
// 검색 (이미 정렬된 슬라이스에서)
i := sort.SearchInts(nums, target)Generics가 들어온 후 — slices
#
Go 1.21+ 에 slices 패키지가 추가됐습니다. 더 모던한 API.
import "slices"
slices.Sort(nums)
slices.SortFunc(users, func(a, b User) int {
return a.Age - b.Age
})
slices.Contains([]string{"a", "b"}, "a")
slices.Index([]int{10, 20, 30}, 20) // 1
slices.Reverse(nums)
slices.Min(nums)
slices.Max(nums)새 코드에서는 slices 패키지가 점점 더 흔해지고 있습니다.
maps — 맵 도구
#
import "maps"
maps.Keys(m) // 모든 키 (이터러블, 슬라이스로 모으려면 slices.Collect)
maps.Values(m)
maps.Equal(a, b)
maps.Clone(m)
maps.Delete(m, fn)errors — 에러 도구
#
#2 에러 처리에서 자세히 다룸.
errors.New("message")
errors.Is(err, target)
errors.As(err, &target)
errors.Join(err1, err2, err3)
errors.Unwrap(err)net/http — HTTP 클라이언트와 서버
#
resp, err := http.Get("https://example.com")
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
// 자기만의 클라이언트
client := &http.Client{Timeout: 5 * time.Second}
req, _ := http.NewRequestWithContext(ctx, "POST", url, body)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "users")
})
http.ListenAndServe(":8080", nil)실전 시리즈에서 본격적으로 다룹니다.
regexp — 정규식
#
re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
match := re.FindStringSubmatch("2026-05-04")
// match: ["2026-05-04", "2026", "05", "04"]
re.MatchString("foo")
re.ReplaceAllString("a1 b2", "X")
re.FindAllString("a1 b2 c3", -1)bufio — 버퍼된 IO
#
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// ...
}
if err := scanner.Err(); err != nil {
// ...
}
// 또는 Reader
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')대용량 파일을 한 줄씩 읽을 때 — os.ReadFile보다 메모리에 안전한 패턴입니다.
log와 log/slog — 로깅
#
옛 log는 단순한 출력.
log.Println("info")
log.Fatalf("fatal: %v", err) // 출력 후 os.Exit(1)Go 1.21+ 의 log/slog — 구조적 로깅 (key-value 쌍).
import "log/slog"
slog.Info("user logged in", "user_id", "u1", "ip", "127.0.0.1")
slog.Error("DB 실패", "err", err)
// JSON 출력
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(logger)JSON 출력은 — 로그 분석 도구(Datadog, Grafana 등)와의 통합이 매우 편합니다. 새 코드에서는 slog가 점점 표준이 되고 있습니다.
flag — 명령줄 플래그
#
import "flag"
var (
host = flag.String("host", "localhost", "서버 주소")
port = flag.Int("port", 8080, "포트")
verbose = flag.Bool("v", false, "verbose")
)
func main() {
flag.Parse()
fmt.Println(*host, *port, *verbose)
}./app --host=0.0.0.0 --port=3000 -vCLI에 더 풍부한 기능이 필요하면 — cobra, kong 같은 외부 라이브러리. 표준 flag만으로도 작은 도구는 충분합니다.
다른 자주 쓰는 패키지들 — 짧게 #
crypto/rand 보안 난수
crypto/sha256 해시
encoding/base64
encoding/hex
encoding/csv
encoding/xml
hash/fnv 빠른 해시 (보안 X)
math
math/rand 비보안 난수
net 저수준 네트워킹
net/url URL 파싱
sync Mutex, WaitGroup, Once, Map
sync/atomic 원자적 연산
unicode 유니코드 도구
unicode/utf8 UTF-8 인코딩마무리 #
이번 글은 인덱스에 가까운 글이었습니다. 자세한 사용법은 pkg.go.dev/std에서 각 패키지를 보세요.
자주 만나는 경우:
- 문자열 →
strings,fmt,strconv - 시간 →
time - JSON →
encoding/json - 정렬 →
sort또는slices(Go 1.21+) - HTTP →
net/http - 로깅 →
log/slog(Go 1.21+) - IO →
os,io,bufio
중급 시리즈를 마치며 #
7편에서 다룬 내용:
- 인터페이스 — 암묵적 구현 (#1)
- 에러 처리 — wrap, Is/As, panic (#2)
- 고루틴과 채널 — 동시성 입문 (#3)
- select와 타임아웃 — 여러 채널 다루기 (#4)
- context — 표준 취소/타임아웃 도구 (#5)
- 테스팅 — testing 패키지와 table-driven (#6)
- 표준 라이브러리 투어 — 자주 만나는 패키지 (이번 글)
여기까지 잡으면 Go로 견고한 코드를 짤 수 있습니다. 다음 고급 시리즈에서는 — 동시성 패턴 깊이, 메모리 모델, 제네릭, reflect 같은 한 단계 위 도구들을 다룹니다.