이 글은 Effective Go를 일부 번역한 글입니다.


자료

생성자와 혼합 리터럴

가끔 0 값으로는 충분하지 않고 초기 설정 생성자가 필요할 때가 있다. 아래 os 패키지에서 가져온 예를 보자.

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }
    f := new(File)
    f.fd = fd
    f.name = name
    f.dirinfo = nil
    f.nepipe = 0
    return f
}

재사용 문구(Boilerplate)가 상당히 많다. 우린 이걸 혼합 리터럴로 축약할 수 있다. 혼합 리터럴은 계산할 때마다 새 개체(Instance)를 만드는 표현이다.

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }
    f := File{fd, name, nil, 0}
    return &f
}

C와 다르게, 지역 변수 주소를 반환해도 온전하단 걸 눈여기라. 변수 저장 공간은 함수 반환 뒤에도 살아남는다. 사실은 혼합 리터럴에서 주소를 가져갈 때마다 새 개체를 할당하기 때문에 마지막 두 줄도 합칠 수 있다.

   return &File{fd, name, nil, 0}

혼합 리터럴의 영역은 순서대로 나열하며, 반드시 모두 나타내야 한다. 하지만, 요소를 명시적으로 영역:값 쌍으로 이름하면 초기 설정자 순서는 상관 없게 된다. 이때 빠진 건 각각에 맞는 0 값으로 만든다. 따라서 우린 이렇게 쓸 수 있다.

   return &File{fd: fd, name: name}

극단적인 경우, 혼합 리터럴 영역을 아예 비우면 그 형의 0 값을 만든다. new(File)과 &File{} 표현은 동일하다.

혼합 리터럴에 색인이나 맵 열쇠를 영역 이름으로 넣어 배열, 조각, 맵을 만들 수도 있다. 아래 예에서 Enone, Eio, Einval 값을 구별할 수만 있다면 값에 상관 없이 초기 설정이 가능하다.

a := [...]string   {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
s := []string      {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}