Go 언어 핵심 개념 정리

메서드 접근 제한

Go에서는 메서드 이름의 첫 글자가 소문자면 패키지 내부에서만 접근 가능하며, 대문자로 시작하면 외부 패키지에서도 사용 가능하다.

시간 처리 기법

// 현재 시간 타임스탬프 가져오기
timestamp := strconv.Itoa(int(time.Now().Unix()))

// 특정 시간 이전 타임스탬프 계산 (예: 30분 전)
var seconds int64
switch duration {
case "15m":
    seconds = 15 * 60
case "30m":
    seconds = 30 * 60
}
pastTimestamp := strconv.Itoa(int((time.Now().Unix() - seconds) * 1000))

배열을 JSON으로 직렬화 및 역직렬화

// 배열 → JSON 문자열
jsonData, err := json.Marshal(dataArray)

// JSON → 맵 변환
resultMap := make(map[string]interface{})
err = json.Unmarshal(jsonData, &resultMap)

MD5 해시 생성

w := md5.New()
io.WriteString(w, "원본 문자열")
hash := fmt.Sprintf("%x", w.Sum(nil))

문자열 결합 방법

  • 기본 연산자 + 사용
  • bytes.Buffer를 활용해 효율적인 결합 가능
buf := bytes.NewBufferString("")
buf.WriteString("Hello")
buf.WriteString(" ")
result := buf.String()

변수 타입 확인

reflect.TypeOf(variable)

맵 선언 및 사용

kvMap := make(map[string]string)
kvMap["key"] = "value"

make와 new 차이점

  • make: 슬라이스, 맵, 채널 초기화 시 사용. 내부 구조 생성 후 실제 값 반환.
  • new: 모든 타입에 적용 가능. 메모리 할당 후 0값 설정, 포인터 반환.
// make 예시
slice := make([]int, 5, 10)
mapData := make(map[string]int)
channel := make(chan int, 5)

// new 예시
ptr := new(int)
slicePtr := new([]int)

rune과 byte의 차이

  • byte: 1바이트, ASCII 문자용 (유니코드 코드 포인트는 8비트 초과 시 오류 발생)
  • rune: 4바이트, 유니코드 전체 지원 (한글 등 다중 바이트 문자 처리 필수)
s := "안녕 세상"
fmt.Println(len(s))                    // 9 (UTF-8 인코딩 기준)
fmt.Println(utf8.RuneCountInString(s)) // 5 (실제 문자 수)

for i, r := range s {
    fmt.Printf("%d: %c\n", i, r)
}

panic과 recover의 동작 원리

panic은 비정상적인 상태에서 프로그램 종료를 유도하고, recoverdefer 블록 내에서만 호출 가능하여 크래시를 회피할 수 있다. 일반적으로 웹 서버에서 요청 단위의 오류 격리에 사용된다.

sync.Map vs 일반 맵 + 락

sync.Map는 읽기 전용 스레드 안정성과 지연 삭제 전략을 통해 고성능 읽기 중심 작업에 최적화되어 있으며, 키 집합이 안정적이고 쓰기 빈도가 낮은 경우에 적합하다.

// sync.Map 사용 예시
var cache sync.Map

cache.Store("user", 123)
if val, ok := cache.Load("user"); ok {
    fmt.Println(val.(int))
}

cache.Range(func(key, value interface{}) bool {
    fmt.Println(key, value)
    return true
})

select 문의 특성과 활용

select는 여러 채널 중 하나가 준비되었을 때 무작위로 실행되며, 기본 케이스 없이 모든 채널이 준비되지 않으면 블로킹된다. 주로 비차단 연산, 멀티플렉싱, 타임아웃, 종료 신호 감지에 사용된다.

func exampleSelect() {
    ch1 := make(chan int)
    ch2 := make(chan int)

    go func() { ch1 <- 1 }()
    go func() { ch2 <- 2 }()

    select {
    case v := <-ch1:
        fmt.Println("from ch1:", v)
    case v := <-ch2:
        fmt.Println("from ch2:", v)
    default:
        fmt.Println("no data available")
    }
}

iota의 의미와 사용 패턴

iotaconst 블록 내에서 자동 증가하는 상수 카운터로, 열거형 또는 비트 마스크 생성에 유용하다. 한 줄마다 1씩 증가하며, _로 생략해도 카운터는 계속 증가한다.

go test 옵션 및 성능 테스트 실행

  • -v: 세부 출력
  • -run=TestName: 특정 테스트 함수 실행
  • -count=N: 반복 실행 횟수
  • -cover: 커버리지 표시
  • -bench: 벤치마크 함수 실행
go test -v -cover ./...
go test -bench=. -benchmem
go test -bench=. -cpuprofile=cpu.prof

싱글톤 패턴 구현

sync.Once를 사용하면 병렬 환경에서도 한 번만 초기화되며, 매우 효율적인 동시성 보장이 가능하다.

type singleton struct{}

var instance *singleton
var once sync.Once

func GetInstance() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

태그: go concurrency synchronization JSON time

6월 3일 21:19에 게시됨