Почему нет дженериков в Go?

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

Кто-нибудь знает, почему нет реальной поддержки для generics/templates/whatsInAName в Go? Таким образом, существует общий map, но предоставленный компилятором, в то время как программист Go не может написать свою собственную реализацию. Со всем разговором о том, как сделать Go максимально ортогональным, почему я могу использовать общий тип, но не CREATE новый?

Особенно, когда речь заходит о функциональном программировании, есть лямбды, даже замыкания, но с системой статического типа, не имеющей дженериков, как я пишу, ну, общие функции более высокого порядка, такие как filter(predicate, list)? OK, Связанные списки и т.п. Могут быть сделаны с interface{} безопасностью типа жертвы.

Поскольку быстрый поиск по SO/Google не выявил каких-либо прозрений, похоже, что дженерики, если вообще будут, будут добавлены к Go в качестве запоздалой мысли. Я действительно доверяю Томпсону, чтобы сделать что-то лучше, чем Java-ребята, но зачем хранить генералы? Или они планируются и еще не реализованы?

Ответ 1

этот ответ вы найдете здесь: http://golang.org/doc/faq#generics

Почему у Go нет общих типов?

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

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

Это остается открытой проблемой.

Ответ 2

Go 2

Черновик проекта для дженериков есть в https://blog.golang.org/go2draft.

Go 1

Расс Кокс, один из ветеранов Go, написал пост в блоге под названием "Общая дилемма", в котором он спрашивает

... вам нужны медленные программисты, медленные компиляторы и раздутые двоичные файлы или медленное время выполнения?

Медленные программисты, являющиеся результатом отсутствия универсальных шаблонов, медленные компиляторы вызваны C++, такими как универсальные шаблоны, и медленное время выполнения основано на подходе распаковки блоков, который используется в Java.

Четвертая возможность, не упомянутая в блоге, идет по маршруту С#. Генерация специализированного кода, как в C++, но во время выполнения, когда это необходимо. Мне действительно это нравится, но Go очень не похож на С#, так что это, вероятно, вообще не применимо…

Я должен отметить, что использование популярной Java 1.4-подобной техники универсального программирования в go , которая приводит к interface{}, страдает точно такими же проблемами, как бокс-распаковка (потому что то, что мы делаем), кроме потери безопасности типа времени компиляции. Для небольших типов (например, ints) Go оптимизирует тип interface{} так, чтобы список целых чисел, приведенных к интерфейсу {}, занимал непрерывную область памяти и занимал только вдвое больше места, чем обычные целые. Однако при приведении из interface{} все еще существуют накладные расходы на проверки во время выполнения. Ссылка.

Все проекты, в которых добавлена общая поддержка (их несколько, и все они интересны), единообразно идут по пути C++ генерации кода времени компиляции.

Ответ 3

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

Вот одна из таких реализаций: http://clipperhouse.github.io/gen/

Ответ 4

На самом деле, согласно этому сообщению:

Многие люди (неправильно) пришли к выводу, что позиция команд Go - "У Go никогда не будет дженериков". Напротив, мы понимаем, что потенциальные дженерики могут сделать Go более гибким и мощным и сделать Go гораздо более сложным. Если мы хотим добавить дженерики, мы хотим сделать это таким образом, чтобы получить как можно большую гибкость и мощность при минимальной дополнительной сложности, насколько это возможно.

Ответ 5

Параметрический полиморфизм (дженерики) находится на рассмотрении для Go 2.

Этот подход вводит концепцию контракта, которую можно использовать для выражения ограничений на параметры типа:

contract Addable(a T) {
  a + a // Could be += also
}

Такой договор может быть использован таким образом:

func Sum(type T Addable)(l []T) (total T) {
  for _, e := range l {
    total += e
  }
  return total
}

Это предложение на данном этапе.


Ваша функция filter(predicate, list) может быть реализована с параметром типа, подобным этому:

func Filter(type T)(f func(T) bool, l []T) (result []T) {
  for _, e := range l {
    if f(e) {
      result = append(result, e)
    }
  }
  return result
}

В этом случае нет необходимости ограничивать T