10.2Kпросмотров
24 января 2026 г.
Score: 11.2K
😳😳 proposal: spec: generic methods for Go 😳😳 Я не так часто пишу тексты в выходные, но тут случилось исключение, которое я не ожидал увидеть от слова «совсем»: Go Team (а именно Роберт Гризмер, один их трех «столпов» Go) предлагает добавить в язык дженерик методы. Тут надо сделать отступление: просьбы об этом от сообщества шли давно. Невозможность иметь дженерик методы существенно усложняла часть кода и делала невозможными «поточные» типы. Но сами просьбы разбивались о взаимодействие интерфейсов и дженерик методов у типов: настолько часты были эти просьбы и ответное разъяснение, что в Go FAQ есть специальный пункт про это, который я очень рекомендую прочитать что-бы осознать суть (и глубину) проблемы. We do not anticipate that Go will ever add generic methods Так что-же поменялось? Ну во первых «запрос о добавлении дженерик методов в Go» один из самых популярных. 49085 набрало больше 900 положительных emoji, а вопрос «как сделать дженерик методы в Go» остается одним из самых популярных на профильных ресурсах. Во вторых сам Роберт предполагает, что изначальная постановка о дуализме «методы <-> интерфейсы» может быть неверна. В чем суть нового предложения? По сути предлагается разрешить следующую запись: type S struct { ... } func (S) mP any { ... } type G[P any] struct{ ... } func (G[P]) mQ any { ... } Да-да, теперь можно написать те самые Type[In any].Map[Out any] методы к которым привыкли программисты из С++/Java|C#. При этом эти методы обладают двумя значимыми ограничениями: Они не реализуют интерфейс даже при совпадении имени и сигнатуры. type I interface { m(int) } type H struct{ … } func (H) mP any { … } var h H var _ I = h // ошибка: сигнатура H.m где mP any не удовлетворяет m(int) типа I Пример который более приближен к реальности type Reader struct{ … } func (Reader) ReadE any (int, error) { … } Не удовлетворяет io.Reader даже если в коде есть вызовы (Reader).Read[byte]. Их нельзя «увидеть» с помощью пакета reflection.
Так как инстанцирование методов происходит во время компиляции, рантайм банально не знает как «увидеть» этот метод динамически. И вызвать его тоже не может. Сам proposal прописывает довольно много технических подробностей и необходимую работу внутри компилятора (которой, на удивление, относительно немного). Но главное тут другое: основная мотивация это удобство записи: x.a().b().c() писать легче чем c(b(a(x)) и отсутствие дженерик методов существенно усложняет процесс портирования streaming типов из других языков. Насколько хороша эта мотивация покажет время, но тот факт, что автором предложения является один из оригинальных авторов языков, а так-же то, что предложение (на данный момент) позитивно принято сообщество (400+ позитивных emoji) наводит на мысль, что проблема действительно актуальна. P.S: оригинальный proposal про дженерики содержал такой параграф. Or, we could decide that parameterized methods do not, in fact, implement interfaces, but then it's much less clear why we need methods at all. If we disregard interfaces, any parameterized method can be implemented as a parameterized function. Те авторы уже изначально закладывали вариант, что могут и передумать. Ну вот и передумали. 😁️️️️️️