프로그래밍백엔드 개발자

Go에서 init 함수는 어떻게 작동하나요? 패키지 내에서 초기화는 어떻게 이루어지며 의존성 및 초기화 순서를 올바르게 관리하는 방법은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

Go는 main()이 시작되기 전에 초기화 코드를 실행하기 위해 init 함수를 지원합니다. Go 프로그램이 실행되면 컴파일러는 각 패키지에 선언된 모든 init 함수를 패키지 변수가 초기화된 후 자동으로 호출합니다.

질문의 배경: 패키지를 사용하기 전에 상태를 한 번만 준비할 필요성.

문제: init의 초기화 순서가 종종 암묵적인 오류의 원인이 됩니다: 특히 패키지 간의 의존성이 많을 경우 특정 init 함수가 언제 실행될지 제어하기 어렵습니다.

해결책:

  • 각 패키지에서 func init() 시그니처를 가진 함수를 허용합니다. 호출은 임포트 의존성에 따라 결정되는 순서로 이루어집니다. init 함수 남용을 피하는 것이 좋으며 최소한의 코드로 유지하는 것이 권장됩니다.

코드 예시:

package example import "fmt" var Cfg string = "default" func init() { fmt.Println("example init") Cfg = "configured" }

주요 특징:

  • 모든 init 함수는 글로벌/패키지 변수가 초기화된 후 호출됩니다.
  • 여러 init 함수가 있다면 호출 순서가 파일 내 선언 순서와 같습니다.
  • 패키지 초기화 순서는 임포트 트리에 따라 결정되며 의존성 먼저, 그 다음 패키지입니다.

함정 질문들.

하나의 파일에서 여러 init 함수를 정의할 수 있나요?

네, 여러 init 함수를 정의할 수 있으며 선언 순서로 호출됩니다.

패키지가 간접적으로 임포트 된다면( _ "package" 를 통해) 무슨 일이 발생하나요?

해당 패키지의 init 함수와 변수 초기화만 수행됩니다.

Init 함수는 값을 반환할 수 있거나 오류를 반환할 수 있나요?

아니요. init 시그니처는 변경되지 않으며: func init(), 매개변수나 반환값이 없습니다.

일반적인 오류 및 안티패턴

  • 복잡한 비즈니스 논리 또는 무거운 초기화를 위한 init 사용.
  • 여러 패키지를 통해 init에서 변수의 숨겨진 변경으로 인해 예측할 수 없는 동작 발생.
  • 필요 없는 여러 init 함수.

실생활의 예

부정적인 사례

대형 프로젝트가 패키지 간 의존성이 있는 전역 상태를 초기화하는 복잡한 init 함수에 의존했습니다. 이는 실행 중에 플로팅 오류를 발생시켰습니다.

장점:

  • 초기화가 단순화됨(메인에서 명시적으로 호출할 필요 없음).

단점:

  • 접근 및 순서 의존성으로 인해 테스트와 디버깅이 어려워짐.

긍정적인 사례

Init는 기본 또는 테스트 전용 작업에만 사용되며 나머지는 main()에서 호출되는 명시적 함수로 분리됩니다. 실행 순서가 명확하며 테스트가 용이합니다.

장점:

  • 실행 및 의존성 관리의 투명성.

단점:

  • 초기화 함수를 명시적으로 호출해야 하며 코드가 조금 더 많아짐.