Статья написана как ответ на ранее опубликованный антиподическая статья .
Последние два с лишним года я использую Go для реализации специализированного RADIUS-сервера с развитой биллинговой системой.
Попутно я изучаю тонкости самого языка.
Сами программы очень просты и не являются целью данной статьи, но сам опыт использования Go заслуживает нескольких слов в свою защиту.
Go становится все более популярным языком для серьезного масштабируемого кода.
Язык создан компанией Google, где он активно используется.
В итоге я искренне считаю, что дизайн языка Go плох для НЕумных программистов.
Предназначен для слабых программистов?
Слабые говорят о проблемах.Go очень прост в освоении, настолько прост, что вы можете читать код практически без какого-либо обучения.Сильный разговор об идеях и мечтах.
Эта особенность языка используется во многих мировых компаниях, когда код читается совместно с непрофильными специалистами (менеджерами, клиентами и т. д.).
Это очень удобно для таких методологий, как разработка через дизайн.
Даже начинающие программисты уже через неделю-две начинают выдавать вполне приличный код. Книга, которую я использовал для изучения Go, называется «Программирование на Go» (автор — Марк Саммерфилд).
Книга очень хорошая, затрагивает многие нюансы языка.
После неоправданно сложных языков, таких как Java, PHP, отсутствие магии освежает. Но рано или поздно у многих ограниченных программистов возникает желание использовать старые методы в новой области.
Действительно ли это необходимо? Роб Пайк (главный идеолог языка) создал язык Go как промышленный язык, простой для понимания и эффективный в использовании.
Язык создан для максимальной продуктивности в больших командах и в этом нет никаких сомнений.
Многие начинающие программисты жалуются, что им не хватает многих функций.
Это стремление к простоте было сознательным решением разработчиков языка, и чтобы полностью понять, зачем оно было нужно, мы должны понять мотивацию разработчиков и то, чего они пытались достичь в Go. Так почему же все было сделано так просто? Вот пара цитат Роба Пайка:
Ключевым моментом здесь является то, что наши программисты не являются исследователями.Мудрые слова, не правда ли? Артефакты простотыОни, как правило, довольно молодые, приходят к нам после учебы, возможно, изучали Java, или C/C++, или Python. Они не понимают хороший язык, но в то же время мы хотим, чтобы они создавали хорошее программное обеспечение.
Именно поэтому язык должен быть простым для понимания и изучения.
Он должен быть знаком, грубо говоря, схож с C. Программисты, работающие в Google, рано начинают свою карьеру и в основном знакомы с процедурными языками, в частности с семейством C. Требование быстрой производительности при использовании нового языка программирования означает, что язык не должен быть слишком радикальным.
Простота – необходимое условие красоты.Сохранение простоты — одна из самых важных целей в любом дизайне.Лев Толстой.
Как известно, идеальный проект — это не проект, в который нечего добавить, а тот, из которого нечего убрать.
Многие люди считают, что для решения (или даже выражения) сложных задач необходим сложный инструмент. Однако это не так.
Возьмем, к примеру, язык PERL. Идеологи языка считали, что у программиста должно быть как минимум три разных способа решения одной задачи.
Идеологи языка Го пошли по другому пути; они решили, что одного пути, но действительно хорошего, достаточно для достижения цели.
У этого подхода есть серьезная основа: единственный путь — легче выучить и труднее забыть.
Многие мигранты жалуются, что язык не содержит изящных абстракций.
Да, это так, но это одно из главных преимуществ языка.
В языке содержится минимум магии — поэтому для чтения программы не требуется глубоких знаний.
Что касается многословности кода, то это вообще не проблема.
Хорошо написанная программа на Golang читается вертикально, практически не имея структуры.
Кроме того, скорость чтения программы как минимум на порядок превышает скорость ее написания.
Если учесть, что весь код имеет единообразное форматирование (осуществляется с помощью встроенной команды gofmt), то прочитать несколько лишних строк вообще не проблема.
Не очень выразительно
Искусство не терпит, когда его свободу ограничивают. Точность не входит в его обязанности.Из-за стремления к простоте в Go отсутствуют конструкции, которые в других языках воспринимаются привычными к ним людьми как нечто естественное.
Поначалу это может быть несколько неудобно, но потом вы заметите, что программа читается гораздо проще и однозначнее.
Например, консольная утилита, считывающая стандартный ввод или файл из аргументов командной строки, будет выглядеть так:
Решение той же задачи в D хоть и выглядит несколько короче, но читается не легчеpackage main import ( "bufio" "flag" "fmt" "log" "os" ) func main() { flag.Parse() scanner := newScanner(flag.Args()) var text string for scanner.Scan() { text += scanner.Text() } if err := scanner.Err(); err != nil { log.Fatal(err) } fmt.Println(text) } func newScanner(flags []string) *bufio.Scanner { if len(flags) == 0 { return bufio.NewScanner(os.Stdin) } file, err := os.Open(flags[0]) if err != nil { log.Fatal(err) } return bufio.NewScanner(file) }
import std.stdio, std.array, std.conv;
void main(string[] args)
{
try
{
auto source = args.length > 1 ? File(args[1], "r") : stdin;
auto text = source.byLine.join.to!(string);
writeln(text);
}
catch (Exception ex)
{
writeln(ex.msg);
}
}
Ад копирования
Человек несет ад внутри себя.Новички постоянно жалуются на Go из-за отсутствия дженериков.Мартин Лютер.
Для решения этой проблемы большинство из них используют прямое копирование кода.
Например, функция суммирования списка целых чисел, такие горе-профессионалы считают, что функционал нельзя реализовать иначе, как простым копированием для каждого типа данных.
package main
import "fmt"
func int64Sum(list []int64) (uint64) {
var result int64 = 0
for x := 0; x < len(list); x++ {
result += list[x]
}
return uint64(result)
}
func int32Sum(list []int32) (uint64) {
var result int32 = 0
for x := 0; x < len(list); x++ {
result += list[x]
}
return uint64(result)
}
func main() {
list32 := []int32{1, 2, 3, 4, 5}
list64 := []int64{1, 2, 3, 4, 5}
fmt.Println(int32Sum(list32))
fmt.Println(int64Sum(list64))
}
Язык имеет достаточные средства для реализации таких конструкций.
Например, подойдет общее программирование.
package main
import "fmt"
func Eval32(list []int32, fn func(a, b int32)int32) int32 {
var res int32
for _, val := range list {
res = fn(res, val)
}
return res
}
func int32Add(a, b int32) int32 {
return a + b
}
func int32Sub(a, b int32) int32 {
return a - b
}
func Eval64(list []int64, fn func(a, b int64)int64) int64 {
var res int64
for _, val := range list {
res = fn(res, val)
}
return res
}
func int64Add(a, b int64) int64 {
return a + b
}
func int64Sub(a, b int64) int64 {
return a - b
}
func main() {
list32 := []int32{1, 2, 3, 4, 5}
list64 := []int64{1, 2, 3, 4, 5}
fmt.Println(Eval32(list32, int32Add))
fmt.Println(Eval64(list64, int64Add))
fmt.Println(Eval64(list64, int64Sub))
}
И, хотя наш код оказался несколько длиннее предыдущего случая, он стал обобщенным.
Поэтому нам не составит труда реализовать все арифметические действия.
Многие скажут, что программа на D выглядит существенно короче, и будут правы.
import std.stdio;
import std.algorithm;
void main(string[] args)
{
[1, 2, 3, 4, 5].
reduce!((a, b) => a + b).
writeln;
}
Однако он лишь короче, но не правильнее, поскольку реализация D полностью игнорирует проблему обработки ошибок.
В реальной жизни по мере увеличения сложности логики разрыв быстро сокращается.
Разрыв сокращается еще быстрее, когда вам нужно выполнить действие, которое невозможно выполнить с помощью стандартных языковых операторов.
По ремонтопригодности, расширяемости и читабельности, на мой взгляд, язык Go выигрывает, хотя и проигрывает в многословности.
Обобщенное программирование в ряде случаев дает нам неоспоримые преимущества.
Это наглядно иллюстрирует пакет sort. Итак, чтобы отсортировать любой список, нам просто нужно реализовать интерфейс sort.Interface. import "sort"
type Names []string
func (ns Names) Len() int {
return len(ns)
}
func (ns Names) Less(i, j int) bool {
return ns[i] < ns[j]
}
func (ns Names) Swap(i, j int) {
ns[i], ns[j] = ns[j], ns[i]
}
func main() {
names := Names{"London", "Berlin", "Rim"}
sort.Sort(names)
}
Если вы возьмете любой проект с открытым исходным кодом и запустите команду grep "interface{}" -R, вы увидите, как часто используются запутанные интерфейсы.
Недалекие товарищи сразу скажут, что все это из-за отсутствия дженериков.
Тем не менее, это не всегда так.
Возьмем в качестве примера DELPHI. Несмотря на наличие этих самых дженериков, он содержит специальный тип VARIANT для операций с произвольными типами данных.
Язык Go делает то же самое.
От пушки до воробьев
И смирительная рубашка должна соответствовать размеру безумия.Многие любители экстрима могут утверждать, что в Go есть другой механизм создания дженериков — отражение.Станислав Лец.
И они будут правы.
но только в редких случаях.
Роб Пайк предупреждает нас:
Это мощный инструмент, который следует использовать с осторожностью.Википедия сообщает нам следующее:Его следует избегать без крайней необходимости.
Отражение — это процесс, в ходе которого программа может отслеживать и изменять свою структуру и поведение во время выполнения.Однако, как известно, за все приходится платить.Парадигма программирования, лежащая в основе отражения, называется рефлексивным программированием.
Это разновидность метапрограммирования.
В данном случае это:
- трудности с написанием программ
- скорость выполнения программы
Бездумное использование рефлексии приводит к нечитаемости программ, постоянным ошибкам и низкой скорости.
Как раз то, что программист-сноб может похвастаться своим кодом перед другими, более прагматичными и скромными коллегами.
Культурный багаж Си Цзиньпина? Нет, с разных языков!
Вместе с состоянием наследникам остаются и долги.Несмотря на то, что многие считают, что язык полностью основан на наследии Си, это не так.
Язык включает в себя многие аспекты лучших языков программирования.
Синтаксис
Прежде всего, синтаксис грамматических конструкций основан на синтаксисе языка Си.Однако язык DELPHI также оказал значительное влияние.
Таким образом, мы видим, что лишние скобки, сильно снижающие читабельность программы, полностью удалены.
Язык также содержит оператор «:=", который является родным для языка DELPHI. Понятие пакетов заимствовано из таких языков, как ADA. Объявление неиспользуемых сущностей заимствовано из языка PROLOG.
Семантика
Пакеты были основаны на семантике языка DELPHI. Каждый пакет инкапсулирует данные и код и содержит частные и общедоступные объекты.Это позволяет свести интерфейс пакета к минимуму.
Операция реализации методом делегирования была заимствована из языка DELPHI.
Сборник
Недаром есть шутка: Go разрабатывался во время компиляции программы на C. Одной из сильных сторон языка является его сверхбыстрая компиляция.Идея была заимствована из языка DELPHI. Каждый пакет Go соответствует модулю DELPHI. Эти пакеты перекомпилируются только тогда, когда это действительно необходимо.
Поэтому после очередного редактирования вам не нужно компилировать всю программу, а перекомпилировать только измененные пакеты и пакеты, которые зависят от этих измененных пакетов (да и то, только если изменились интерфейсы пакетов).
Конструкции высокого уровня
Язык содержит множество различных конструкций высокого уровня, которые никак не связаны с языками низкого уровня, такими как C.- Струны
- Хэш-таблицы
- Ломтики
- Утиная типизация заимствована из таких языков, как RUBY (который, к сожалению, многие не понимают и не используют в полной мере).
Управление памятью
Управление памятью вообще заслуживает отдельной статьи.Если в таких языках, как C++, управление полностью оставлено разработчику, то в более поздних языках, таких как DELPHI, использовалась модель подсчета ссылок.
При таком подходе циклические ссылки не допускались, так как образовывались потерянные кластеры, то в Go есть встроенное обнаружение таких кластеров (как в C#).
Кроме того, сборщик мусора более эффективен, чем большинство известных на данный момент реализаций, и уже может использоваться для решения многих задач реального времени.
Язык сам распознает ситуации, когда значение для хранения переменной может быть выделено в стеке.
Это снижает нагрузку на диспетчер памяти и увеличивает скорость работы программы.
Параллелизм и параллелизм
Параллелизм и конкурентоспособность языка выше всяких похвал.Ни один низкоуровневый язык не может даже отдаленно конкурировать с Go. Справедливости ради стоит отметить, что модель не была придумана авторами языка, а просто была заимствована из старого доброго языка ADA. Язык способен обрабатывать миллионы параллельных соединений, используя все процессоры, при этом имея на порядок менее сложные проблемы с взаимоблокировками и состояниями гонки, типичные для многопоточного кода.
Дополнительные преимущества
Если это будет выгодно, все станут самоотверженными.Язык также дает нам ряд несомненных преимуществ:
- Единый исполняемый файл после сборки проекта значительно упрощает развертывание приложений.
- Статическая типизация и вывод типов позволяют существенно снизить количество ошибок в вашем коде даже без написания тестов.
Я знаю некоторых программистов, которые вообще обходятся без написания тестов и качество их кода существенно не страдает.
- Очень простая кросс-компиляция и отличная переносимость стандартной библиотеки, что значительно упрощает разработку кроссплатформенных приложений.
- Регулярные выражения RE2 потокобезопасны и имеют предсказуемое время выполнения.
- Мощная стандартная библиотека, позволяющая большинству проектов обойтись без сторонних фреймворков.
- Язык достаточно мощный, чтобы сосредоточиться на проблеме, а не на том, как ее решить, но при этом достаточно низкоуровневый, чтобы проблему можно было решить эффективно.
- Однако система Go уже содержит развитые инструменты «из коробки» на все случаи жизни: тесты, документацию, управление пакетами, мощные линтеры, генерацию кода, детектор состояний гонки и т.д.
- В версии Go 1.11 представлено встроенное управление семантическими зависимостями, созданное на основе популярного хостинга VCS. Все инструменты, составляющие экосистему Go, используют эти сервисы для загрузки, сборки и установки кода из них одним махом.
И это здорово.
С приходом версии 1.11 проблема с управлением версиями пакетов также была полностью решена.
- Поскольку основная идея языка — уменьшить количество магии, язык стимулирует разработчиков явно выполнять обработку ошибок.
И это правильно, потому что в противном случае об обработке ошибок он просто забудет вообще.
Другое дело, что большинство разработчиков сознательно игнорируют обработку ошибок, предпочитая вместо их обработки просто пересылать ошибку вверх.
- В языке не реализована классическая методология ООП, поскольку в чистом виде в Go нет виртуальности.
Однако это не проблема при использовании интерфейсов.
Отсутствие ООП существенно снижает барьер входа для новичков.
Легко усложнить, трудно упростить.Go был задуман как простой, и он преуспел в достижении этой цели.
Он был написан для умных программистов, которые понимают преимущества командной работы и устали от бесконечной изменчивости языков корпоративного уровня.
Имея в своем арсенале сравнительно небольшой набор синтаксических конструкций, он практически не подвержен изменениям с течением времени, поэтому у разработчиков освобождается много времени для разработки, а не для бесконечного изучения языковых новинок.
Компании также получают ряд преимуществ: низкий входной барьер позволяет быстро найти специалиста, а неизменность языка позволяет использовать один и тот же код даже через 10 лет. Заключение
Большой размер мозга еще ни разу не сделал ни одного слона лауреатом Нобелевской премии.Для тех программистов, у которых личное эго преобладает над командным духом, а также теоретиков, любящих академические задачи и бесконечное «самосовершенствование», язык действительно плох, так как это кустарный язык общего назначения, не позволяющий получить эстетическое удовольствие от результата своей работы и показать себя профессионалом перед коллегами (при условии, что мы измеряем интеллект по этим критериям, а не по IQ).
Как и все в жизни, это вопрос личных приоритетов.
Как и все стоящие инновации, язык уже прошел долгий путь от всеобщего отрицания до массового принятия.
Язык гениален в своей простоте, а, как известно, все гениальное просто! Краткое содержание Среди всей жесткой критики в адрес Го выделяются следующие высказывания:
- Никаких дженериков.
Если мы посмотрим на статистика самых популярных языков, отметим, что половина из первой десятки языков не имеет дженериков.
В основном дженерики нужны только в контейнерах.
Поэтому выигрыш от них не слишком велик.
- Другие языки вроде Rust намного лучше (по крайней мере, по номинациям сайта ХХХ).
Опять же, если мы посмотрим на статистика самых популярных языков, то мы не найдем язык Rust в списке вообще, либо он окажется где-то внизу рейтинга.
Лично мне нравится Rust, но я выбрал Go.
- У языка XXX есть такой бонус.
Это обратная сторона медали простоты.
Недостатком это или нет – решать каждому.
Однако разработчики проекта отдали предпочтение простоте.
- Выпустят Go 2.0, тогда и посмотрим.
Эту позицию занимают наблюдатели, а не практики.
- Недостаточно выразительно.
Я согласен, что в некоторых местах выражения не хватает, но в целом это простой и последовательный язык.
Кроме того, из-за бедности языка мы вынуждены уделять больше внимания архитектуре разрабатываемого приложения, что положительно сказывается на его гибкости.
Подразумевалось, что статья будет продолжена, применительно к более конкретным проблемам.
Однако из-за отсутствия интереса к теме продолжения, скорее всего, не будет. Ээксперимент
Не верьте словам – ни своим, ни чужим, а верьте делам – и своим, и чужим.Заключительная часть предназначена исключительно для той категории людей, которые считают себя конструктивно мыслящими оптимистами и могут подтвердить это своими действиями.
Остальным зрителям, пожалуйста, пропустите эту часть.
На изменение этого эксперимента вдохновили друзья, которые утверждали, что все конструктивно мыслящие оптимисты давно покинули (по крайней мере виртуально) просторы нашей страны и обосновались, например, на Stack Overflow, а те, кто остался здесь, — это в основном снобы.
Я долго им не верил, поэтому решил провести этот эксперимент. На хабе было размещено несколько статей, результат анализа комментариев к которым я представляю.
- Действительно, гипотеза моих друзей подтвердилась; однако среди хакеров еще есть адекватные люди, хотя их процент стремительно падает. Юрий Быков называет таких людей « дураки », на котором держится вся страна.
По его версии, их процент невелик (около 2%).
Я не столь пессимистичен и считаю, что их гораздо больше.
- Закон о СМИ.
Деструктивная информация представляет гораздо больший интерес, чем конструктивная.
- Психология толпы.
Это ужасная вещь, она даже адекватного человека превращает в жестокого барана.
Человек в толпе уже не человек.
Ни о какой объективности не может быть и речи.
Никакие логические аргументы, никакие авторитетные источники и прецеденты на него не действуют.
- Ответственность и безнаказанность.
Люди рады унизить другого, чтобы возвысить себя (хотя бы в собственных глазах).
Особенно если за это не надо отвечать (что может быть проще - нажимаешь минус и даже комментарий писать не нужно).
Между словами и делами остается столько же общего, как между каналом и канализацией.
- Тщеславие.
Большинство снобов готовы выделиться любым способом.
Их не пугают никакие моральные барьеры.
- Пессимизм.
В отличие от стран Запада (и особенно Америки), в стране преобладают пессимистические настроения.
Как известно, оптимист ищет возможности среди трудностей, а пессимист ищет трудности среди возможностей.
В нашей стране на положительные качества чего-либо почти никто не обращает внимания.
- Профессионализм и мировоззрение.
Большинство людей выбирают инструменты как самоцель, а не как средство достижения цели.
Люди разучились работать с информацией.
Люди не видят леса за деревьями.
Из массива информации они не способны выделить основные идеи.
Никто не хочет смотреть с другой, нестандартной точки зрения.
Инакомыслие подавляется.
Здесь дело обстоит иначе.
- Дружба и уважение.
Хваленые дружные коллективы существуют только на словах.
Ценности гибкой разработки существуют только на бумаге.
- Лицемерие.
Вообще об этом можно написать отдельную статью.
- Честность.
Есть люди, которые задают правильный вопрос: « Что, черт возьми, я вообще делаю? Однако не все понимают, что из-за беспринципности сиюминутный корыстный интерес для нас важнее всех наших принципов вместе взятых.
Самый простой способ – свалить все на обстоятельства и сказать, что от нас ничего не зависит.
Адверакс.
Теги: #программирование #Go #golang #ИТ-эмиграция #сравнение #язык программирования #Изучение языков #выбор
-
Тт Киберспорт Уровень 10 М - Просто Мышка?
19 Oct, 24 -
Немного О Сбербанке
19 Oct, 24 -
Opera 11.00 Релиз-Кандидат 1
19 Oct, 24 -
Джевикс
19 Oct, 24