Go 모범 사례 및 관용구
Go 에서 context.Context의 목적은 무엇이며 언제 사용해야 하나요?
답변:
context.Context는 API 경계 및 프로세스 간에 마감일, 취소 신호 및 기타 요청 범위 값을 전달하는 데 사용됩니다. 고루틴의 수명을 관리하는 데 중요하며, 특히 HTTP 요청 또는 데이터베이스 호출과 같은 동시 작업에서 정상적인 종료 및 리소스 정리를 허용합니다.
Go 오류 처리에서 'Fail fast' 개념을 설명해주세요.
답변:
Go 에서 'Fail fast'는 오류가 발생하는 즉시 처리하는 것을 의미하며, 일반적으로 즉시 반환합니다. 이렇게 하면 프로그램이 잘못된 상태로 계속 실행되는 것을 방지하고 디버깅을 더 쉽게 만듭니다. 실패할 수 있는 작업 후에 if err != nil { return err }를 확인하여 달성하는 경우가 많습니다.
Go 에서 메서드에 포인터 수신자 (pointer receiver) 를 사용해야 하는 경우와 값 수신자 (value receiver) 를 사용해야 하는 경우는 언제인가요?
답변:
메서드가 수신자의 상태를 수정해야 하거나 수신자가 크고 복사하는 것이 비효율적일 때는 포인터 수신자 (func (p *MyType) Method()) 를 사용합니다. 메서드가 수신자의 상태만 읽고 수정할 필요가 없을 때는 값 수신자 (func (v MyType) Method()) 를 사용합니다. 이 경우 복사본으로 작동합니다.
Go 에서 'comma ok' 관용구는 무엇이며 어디에 흔히 사용되나요?
답변:
'comma ok' 관용구 (value, ok := expression) 는 작업이 성공했는지 또는 값이 존재하는지 확인하는 데 사용됩니다. 타입 어설션 (v, ok := i.(T)), 맵 조회 (v, ok := m[key]), 채널 수신 (v, ok := <-ch) 에 흔히 사용되어 제로 값과 존재하지 않거나 실패한 상태를 구별합니다.
'메모리를 공유하여 통신하지 말고, 통신하여 메모리를 공유하라'는 Go 격언을 설명해주세요.
답변:
이 격언은 명시적인 잠금으로 공유 메모리에 의존하는 대신 채널을 사용하여 고루틴 간에 데이터를 전달하는 것을 강조합니다. 데이터 소유권이 이전되는 동시 프로그래밍을 촉진하여 복잡한 뮤텍스의 필요성을 줄이고 경쟁 상태를 최소화하여 더 강력하고 이해하기 쉬운 동시 코드를 만듭니다.
Go 에서 init() 함수의 목적은 무엇이며 어떤 특징이 있나요?
답변:
init() 함수는 패키지가 초기화될 때 main() 이전에 자동으로 실행되는 특수 함수입니다. 패키지 수준 상태 설정, 서비스 등록 또는 일회성 초기화 작업 수행에 사용됩니다. 패키지는 여러 개의 init() 함수를 가질 수 있으며, 소스 파일에 나타나는 순서대로 실행됩니다.
Go 에서 '임베딩 (embedding)' 개념과 그 이점을 설명해주세요.
답변:
Go 의 임베딩은 구조체가 다른 구조체 또는 인터페이스 타입을 직접 포함할 수 있도록 하여 상속보다 구성을 촉진합니다. 임베딩된 타입의 필드와 메서드는 외부 구조체로 승격되어 위임 및 코드 재사용의 한 형태를 제공합니다. 임베딩된 멤버에 명시적인 필드 이름 없이 직접 액세스할 수 있도록 하여 코드를 단순화합니다.
고루틴을 조정하기 위해 sync.WaitGroup을 사용해야 하는 경우와 채널을 사용해야 하는 경우는 언제인가요?
답변:
sync.WaitGroup은 고정된 수의 고루틴이 작업을 완료할 때까지 기다리는 데 가장 적합합니다. 카운트를 Add하고, 각 고루틴은 완료 시 Done()을 호출하며, 메인 고루틴은 Wait()합니다. 채널은 고루틴 간에 데이터를 통신하거나, 이벤트를 신호하거나, 데이터 교환이 주요한 복잡한 워크플로를 조정하는 데 더 적합합니다.
Go 표준 라이브러리의 로깅 접근 방식은 무엇이며, 일반적인 모범 사례는 무엇인가요?
답변:
표준 라이브러리의 log 패키지는 기본적인 로깅 기능을 제공합니다. 모범 사례에는 파싱 및 분석을 더 쉽게 하기 위해 구조화된 데이터 (예: JSON) 를 로깅하고, 적절한 로그 수준 (info, warn, error) 을 사용하며, 성능이 중요한 경로에서 과도한 로깅을 피하는 것이 포함됩니다. 프로덕션 환경에서는 외부 로깅 라이브러리가 회전 및 다른 출력과 같은 더 많은 기능을 제공하는 경우가 많습니다.
모범 사례에 따라 Go 애플리케이션에서 구성을 어떻게 처리하나요?
답변:
구성 모범 사례에는 민감한 데이터 및 배포별 설정에는 환경 변수를 사용하고, 애플리케이션별 매개변수에는 구성 파일 (예: JSON, YAML, TOML) 을 사용하는 것이 포함됩니다. viper 또는 koanf와 같은 라이브러리를 사용하여 여러 소스를 관리할 수 있습니다. 코드에 직접 구성을 하드코딩하는 것은 피해야 합니다.