(Технически это называется «Параметрический полиморфизм», но это нормально)

Эта статья представляет собой краткое изложение текущего состояния дженериков в Go на момент публикации этой статьи. Вы найдете цитаты создателей (на самом деле только Роба Пайка), примеры синтаксиса и цитаты.

В этой статье вы найдете

  • Краткое введение
  • Обзор текущего проекта
  • Мнения Роба Пайка о проекте
  • Примеры и случаи синтаксиса
  • Остающиеся вопросы по проекту
  • Понимание того, когда ожидать дженериков
  • Цитаты

Краткое введение

Большинство из нас, читающих эту статью, уже знают, что такое дженерики и что они означают для Go. Этот раздел больше предназначен для тех, кто не знаком с универсальными шаблонами и хочет быстрее узнать об этом предмете.

Иногда то, что вы хотите сделать, не имеет ничего общего с типом, с которым вы это делаете.

- Роб Пайк

Обобщения (или параметрический полиморфизм) позволяют нам писать функции, которые могут применять алгоритмы к входящим параметрам таким образом, чтобы не заставлять нас использовать тип, указанный в объявлении функции.

Представьте себе, что у вас есть структура Thing, и вам нужно отсортировать Thing срез по его ключевому свойству.

Вы создаете SortThings функцию, и это здорово. Однако предположим, что появляется новая структура, и она выглядит похожей, но немного отличается.

Допустим, вам нужно отсортировать часть из них, используя тот же метод сортировки, который используется в функции SortThings.

В настоящее время вам нужно скопировать / вставить код внутри SortThings и создать новую функцию с именем SortAnotherOne, где все то же самое, кроме типа входного параметра.

Введите Generics.

Вы можете переписать указанную выше функцию, где она принимает тип в качестве параметра наряду с параметрами функции.

Это позволяет нам повторно использовать код способами, которые мы не могли раньше, или должны были выполнять (относительно) небезопасное приведение типов постфактум.

Обзор текущего проекта

Перейдите по следующей ссылке, чтобы увидеть текущий черновик. Это может сильно измениться, прежде чем станет предложением.



Интересная часть того, как сообщество Go разрабатывает языковые функции в целом, заключается в том, что мы начинаем с синтаксиса. После согласования разработчикам компилятора остается найти способы его реализовать.

Почему бы не начать с того, что вы пытаетесь выразить, и позволить разработчикам компилятора сказать: «У меня есть хороший способ реализовать это»

- Роб Пайк

Возможно, именно этот социальный и инклюзивный подход делает Go таким эргономичным для решения множества различных проблем, в любом случае он подразумевает, что для достижения консенсуса требуется время.

Проект

В приведенном ниже примере описывается простая функция, использующая универсальный тип.

Вы видите, что вы объявляете функцию, в которой есть два места для ввода. Первый набор круглых скобок обозначает типы ввода, а второй - параметры функции.

Отсюда вы можете вызвать функцию, передав параметры типа и функции.

Ожидается, что для простых случаев типы могут быть выведены из входных данных, что означает, что вы можете напрямую использовать функцию без явного указания типа.

Теперь мы сталкиваемся с проблемами, когда функции реализуют универсальный тип, но для этого типа нет ожидаемого метода или оператора, однако функция вызывает его для его использования.

См. Следующий пример:

Но что, если в переданном типе нет оператора <? (как в случае с string)

Интуитивно кажется, что компилятор будет иметь достаточно информации во время компиляции, чтобы знать, не соответствует ли ввод требованиям функции.

Первоначально Ян Лэнс Тейлор попытался реализовать, чтобы компилятор мог анализировать функции во время компиляции и выяснять, как выглядит удовлетворение типа, чтобы уловить эти случаи, однако реализация стала слишком большой.

В какой-то момент он понял, что это вышло из-под контроля, реализация, и это никогда не будет реализовано, и ему нужен был более простой и ясный способ сказать «это то, что я хочу».

- Роб Пайк

Заключать контракты

Контракты - это декларативный способ описания того, что должно существовать в вашем типе, чтобы его можно было использовать.

Приведенный выше пример с контрактом будет выглядеть так

При этом мы говорим, что любой тип, который вы проходите, должен соответствовать требованиям контракта, чтобы быть принятым.

В частности, в этом случае тип должен иметь возможность решать < против самого себя, разрешая int, но не выполняя string, bool или структуру.

Я думаю, было бы здорово, если бы мы могли создать версию параметрического полиморфизма для Go, которая будет похожа на Go, когда мы закончим.

Мне это кажется довольно несговорчивым.

Но как вы можете сказать, что тип может быть преобразован в int или целочисленная константа любого типа может быть там.

Я думаю, что где-то на этом слайде (черновике) есть блестящая идея, которая сделает все по-настоящему ясным и простым.

Но, может быть, для начала нам не нужны контракты?

- Роб Пайк

Заключение

Параметрический полиморфизм (дженерики) - мощное средство, устраняющее ряд неудобств языка, а также открывающее двери для возможностей новых типов библиотек и выразительных стилей программирования.

В конце концов, Go написан для нас и в значительной степени нами. Мы, как сообщество, можем говорить о тех функциях, которые нам нужны. Обсудите наши варианты использования и изучите проекты.

Лично на меня включение модулей в прошлом году оказало на меня огромное положительное влияние. Заглядывая в будущее, параметрический полиморфизм открывает совершенно новый мир возможностей - от сортировки библиотек до новых механизмов работы с JSON.

Когда дженерики появятся в Go?

Выражая свои чувства на ете, Роб ответил:

Пришло время изменить Go, учитывая то, что мы узнали за последнее десятилетие использования его в производственной среде.

На то, чтобы разобраться с этим, уйдет много времени.

Могут пройти годы, прежде чем что-то действительно будет решено, поэтому…
Пожалуйста, проявите терпение

- Роб Пайк

использованная литература

Встреча на Сиднейском Голанге - Роб Пайк - Проект спецификации Go 2
https://www.youtube.com/watch?v=RIvL2ONhFBI

Контракты - Эскизный проект
https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md

Предложение: Go должен иметь общие шаблоны
https://go.googlesource.com/proposal/+/master/design/15292-generics.md