Go 제네릭의 한계

5776 단어 gogenerics
Go는 메소드 선언에서 유형 매개변수(제네릭)를 허용하지 않으며 이는 만들 수 있는 API를 제한합니다.

다음은 해당 문제가 발생할 수 있는 경우와 해결 방법의 예입니다.

값의 흐름을 처리하기 위해 라이브러리를 구축 중이고 다음 유형으로 시작한다고 가정해 보겠습니다.

// Stream receives In values from upstream and
// sends Out values downstream.
type Stream[In, Out] ...


이상적으로는 다음과 같은 일반.connect() 메서드를 작성할 수 있습니다.

//                           vvvvvvv ❌ not allowed by Go!
func (s Stream[A, B]) connect[C any](o Stream[B, C]) ...


하지만 Go does not allow type parameters in method declarations . 이는 .connect() 메서드가 새로운 유형을 도입할 수 없음을 의미합니다.

//                                                  vvvvvv ✅ OK
func (s Stream[A, B]) connect(o Stream[B, B]) Stream[A, B]


이는 .connect() 메서드를 함께 연결하여 수행할 수 있는 처리 종류를 제한합니다.

lines
    .connect(omitEmpty) // ✅ (string -> string) same type
    .connect(getLength) // ❌ (string -> int   ) new type
    .connect(print)

.connect()를 스트림 유형을 변경할 수 있는 최상위connect() 함수로 변환하여 이 제한을 해결할 수 있습니다 🎉:

func connect[A, B, C any](
    s1 Stream[A, B],
    s2 Stream[B, C],
) Stream[A, C]


불행히도 가독성이 약간 떨어집니다.

connect(connect(connect(lines, omitEmpty), getLength), print)


또는 오른쪽 연관성으로 작성:

connect(lines, connect(omitEmpty, connect(getLength, print)))


또는 별도의 라인에서:

s1 := lines
s2 := connect(s1, omitEmpty)
s3 := connect(s2, getLength)
s4 := connect(s3, print)


스트림의 각 단계마다 별도의 변수가 필요하지만 그 외에는 위의 메서드 체이닝과 크게 다르지 않습니다!

좋은 웹페이지 즐겨찾기