Почему нет генериков в Go? - PullRequest
       14

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

114 голосов
/ 12 октября 2010

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

Кто-нибудь знает, почему нет реальной поддержки дженериков / шаблонов / whatsInAName?на ходу?Таким образом, существует универсальный map, но он предоставляется компилятором, в то время как программист на Go не может написать свою собственную реализацию.Несмотря на все разговоры о том, чтобы сделать Go как можно более ортогональным, почему я могу ИСПОЛЬЗОВАТЬ универсальный тип, а не СОЗДАТЬ новый?

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

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

Ответы [ 4 ]

73 голосов
/ 12 октября 2010

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

Почему у Go нет универсальных типов?

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

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

Этот вопрос остается открытым.

28 голосов
/ 13 октября 2014

Go 2

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

Go 1

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

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

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

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

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

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

9 голосов
/ 18 февраля 2014

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

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

0 голосов
/ 23 января 2019

Параметрический полиморфизм (генерики) - на рассмотрении для 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...