LINUX.ORG.RU

Go 1.9

 


1

6

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

Наиболее важным изменением языка является введение псевдонимов типов. Объявление псевдонима типа выглядит следующим образом:

type T1 = T2

Это объявление вводит псевдоним Т1 для типа Т2, таким же образом, как byte всегда был псевдонимом для uint8. Дизайн-документ псевдонимов типов и статья о рефакторинге объясняют это дополнение более детально.

Новый пакет math/bits предоставляет функции подсчета и обработки битов для целых беззнаковых чисел, которые, когда это возможно, реализуются специальными инструкциями CPU. Например, в системах x86-64 bits.TrailingZeros(x) использует инструкцию BSF.

Пакет sync добавил новый тип Map, безопасный для многопоточного доступа. Важно понимать, что это не общая замена типа Map; обратитесь к документации, чтобы узнать, когда она должна использоваться.

В пакет testing также добавлено дополнение. Новый метод Helper, добавленный к testing.T и testing.B, отмечает вызывающую функцию в качестве тестовой вспомогательной функции. Когда тестовый пакет печатает информацию о файле и строке, он показывает местоположение вызова вспомогательной функции вместо строки в самой вспомогательной функции.

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

Наконец, в рамках усилий, направленных на ускорение работы компилятора, Go 1.9 компилирует функции в пакете одновременно.

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

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

>>> Подробности



Проверено: Klymedy ()
Последнее исправление: Klymedy (всего исправлений: 3)
Ответ на: комментарий от RazrFalcon

Но в rust такой подход считается быдлокодом.

В rust есть более подходящие способы лаконично пробросить ошибки наверх, в go их нет и не предвидится. Только если сообществу удастся доказать core team, что дженерики нужны, они могут появиться в go 2.0

feofan ★★★★★
()
Ответ на: комментарий от NextGenenration

Можно придумать не один пример, когда из-за такой реализации я создаю объект дочернего типа, передаю его куда-то, а оттуда получаю объект родительского типа.

Придумать можно. Но в реальном коде на go я такого не видел.

feofan ★★★★★
()
Ответ на: комментарий от NextGenenration

Что такое деструктор знаешь, что деструкторы объектов вызываются при выбросе исключения в курсе? и при таком подходе в классе через который управляли заполнением XML файла в деструкторы проверят что commit метод не дёрнули и удалят твой файл к чертям/откатят все изменения

lberserq
()
Ответ на: комментарий от NextGenenration

Есть := и переменная, созданная этим оператором будет видна только внутри соответствующего скоупа. Если ты имел ввиду zero value, то это удобно. Главное не пренебрегать обработкой ошибок. Существуют линтеры, которые это проверяют. Не то, чтобы очень хорошо, что это внешний тулинг, а не часть компилятора, но эти линтеры прекрасно встраиваются в CI, а пользователь получает быструю сборку простым и глупым компилятором.

feofan ★★★★★
()
Ответ на: комментарий от NextGenenration

У тебя что привычка пересобирать программу вместе со всеми зависимыми библиотеками?

У всех гоебанов так и происходит.

anonymous
()
Ответ на: комментарий от NextGenenration

Можно придумать не один пример, когда из-за такой реализации я создаю объект дочернего типа, передаю его куда-то, а оттуда получаю объект родительского типа.

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

feofan ★★★★★
()
Ответ на: комментарий от lberserq

Я ни разу не видел деструкторов в c# кроме как в одном месте - мануалу по самому c#. Гораздо проще дописать ветку catch чем вставлять очередную подпорку.

NextGenenration ★★
()
Ответ на: комментарий от feofan

Ты считаешь, что это плохо?

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

NextGenenration ★★
()
Ответ на: комментарий от feofan

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

Хорошо, что выведет компилятор go - интерфейс или реализацию при подобной реализации обобщения?

NextGenenration ★★
()
Последнее исправление: NextGenenration (всего исправлений: 1)
Ответ на: комментарий от NextGenenration

Хорошо, что выведет компилятор go - интерфейс или реализацию при подобной реализации обобщения?

Что программист напишет, то и выведет. Но принято в функцию передавать интерфейсы, а возвращать из функции конкретные типы.

feofan ★★★★★
()
Последнее исправление: feofan (всего исправлений: 1)

Больше всего в Go нравится простая кросскомпиляция: любой экземпляр компилятора умеет компилировать сразу в кучу таргетов.
просто как

$ GOARCH=arm GOOS=linux go build
и через мгновение уже бинарь под arm. Только из-за этого пишу на go больше чем на C. Возиться с gcc и clang это просто ад.

anonymous
()
Ответ на: комментарий от iZEN

Если собирать Go как CGO_ENABLED=0 ./make.bash то получится

ldd ./bin/go
	not a dynamic executable

anonymous
()
Ответ на: комментарий от feofan

Что программист напишет, то и выведет

Явное приведение типов?

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

Вот пример кода на c#. Как я понимаю go работает примерно так

//есть интерфейс и типы его реализующие
interface I {}
class A : I {}
class B : I {}
//есть какие-то методы что-то принимающие и что-то отдающие
class Storage {
public void Set(I i) {}
public I Get() {}
}
То есть есть какой-то код(возможно библиотечный), который что-то делает с какой-то переменной, к примеру запоминает. Проблема в том что я не знаю какой тип я передал в функцию Set - A или B. И без приложения кучи усилий так и не узнаю.

NextGenenration ★★
()
Ответ на: комментарий от iZEN

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

mersinvald ★★★★★
()
Ответ на: комментарий от RazrFalcon

Для конечного пользователя - это одно и то же.

Ну разве что для очень глупого конечного пользователя. Не надо под таких подстраиваться.

Legioner ★★★★★
()
Ответ на: комментарий от RazrFalcon

В GTK+ и Qt - нет.

Ну это проблемы GTK+ и Qt. Хотя я сомневаюсь, что там нельзя этого сделать.

Конечному пользователю пофиг на лог. Ему нужно чтобы прога не падала.

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

А потом жалуются, что плазма падает.

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

Ну нельзя использовать подходы серверной разработки в GUI.

Некоторые подходы универсальны.

Legioner ★★★★★
()
Ответ на: комментарий от NextGenenration

Хорошое «штатно». Допустим создавался xml файл. Половина файла есть, второй половины нет. Это и есть «штатно»?

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

Legioner ★★★★★
()
Ответ на: комментарий от NextGenenration

Явное приведение типов?

Да. В go нет неявного приведения типов.

Как я понимаю go работает примерно так

Приведенный код очень далёк от go и напрямую его переложить не получится. Я предположу, что ты хотел узнать, как выяснить какой именно конкретный тип скрывается за интерфейсом. Внутри функции, принимающей интерфейс это неважно - методов интерфейса должно быть достаточно для того, что делает эта функция. Если же интерфейс возвращать, то узнать какой же конкретный тип за ним скрывается можно только через type switch. Есть еще вариант использовать рефлексию, но она работает медленно имеет ограничения.

feofan ★★★★★
()
Ответ на: комментарий от RazrFalcon

То есть я узнаю об ошибке после пуша в master?

В текстовые редакторы эти линтеры тоже прекрасно встраиваются. Тут с rust ситуация абсолютно симметричная - язык не гарантия отсутствия ошибок в master. Кто тебе помешает залить в реп код, который не собирается?

feofan ★★★★★
()
Ответ на: комментарий от Legioner

Падать в непредвиденной ситуации это правильная работа.

Смотря что есть «непредвиденная ситуация». Сегфолт или неправильный xml.

Некоторые подходы универсальны.

Пропуск исключений - нет.

Продолжать работать в непредвиденной ситуации это неправильная работа.

Можно пример такой ситуации?

RazrFalcon ★★★★★
()
Ответ на: комментарий от Legioner

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

Как там в параллельной вселенной?

ТП пользователь вообще не знает ничего о кодах возврата.

RazrFalcon ★★★★★
()
Ответ на: комментарий от feofan

Я далёк от мира java и не могу опровергнуть этот довод, но мне кажется, что не всё так просто и Checked Exceptions в Java не взлетели не потому, что они Checked. Ну и небольшой поиск показывает, что холивары на эту тему еще не утихли.

Утихли. Даже Oracle в 8 версии практически официально задепрекейтил Checked исключения, введя Unchecked-обёртки. Идея проверяемых исключений может быть и взлетит когда-нибудь, но для этого надо улучшать язык во многих аспектах. Пока я таких языков не видел, поэтому непроверяемые исключения это на данный момент лучший подход к обработке ошибок. Если сделают где-нибудь нормальные проверяемые исключения, может быть они будут лучше, не знаю.

Ну, мне видится, что отсутствие падения еще лучше.

Не понимаю я тебя. Вот у тебя есть ошибка. Пришла она откуда-то. И что ты с ней будешь делать? У тебя есть два варианта: упасть (не обязательно в смысле процесса ОС, возможно просто ответить клиенту 500 Internal Server Error) или проигнорировать ошибку. Всё. Если ты игнорируешь ошибку, ты практически гарантированно нарушаешь предположения следующего кода о том, что предыдущий код отработал нормально. Например ты не смог списать средства со счёта одного пользователя (произошла ошибка), проигнорировал этот факт и начислил эти средства на счёт другого пользователя.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Нет, так работают твои консольные утилитки и серверы, если им подсунуть битый конфиг.

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

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

mersinvald ★★★★★
()
Последнее исправление: mersinvald (всего исправлений: 1)
Ответ на: комментарий от Legioner

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

Ну если тебя волнует только код завершения, и не волнует то что она может поломать половину системы... Тогда всё понятно.

NextGenenration ★★
()
Ответ на: комментарий от Legioner

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

Посмотри rust, подход к обработке ошибок мне очень нравится.

У тебя есть два варианта: упасть (не обязательно в смысле процесса ОС, возможно просто ответить клиенту 500 Internal Server Error) или проигнорировать ошибку. Всё.

Плохо, что не понимаешь. Выше по треду уже были примеры. Далеко не всегда есть только два варианта.

feofan ★★★★★
()
Ответ на: комментарий от feofan

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

Да.

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

Да.

Если же интерфейс возвращать, то узнать какой же конкретный тип за ним скрывается можно только через type switch. Есть еще вариант использовать рефлексию, но она работает медленно имеет ограничения.

К примеру я создаю свою базу данных(бестолковый пример, но лучше пока не придумал). Я правильно понимаю что теперь пользователям придётся писать кучу кода для уточнения типа?

NextGenenration ★★
()
Ответ на: комментарий от RazrFalcon

Поломанный CI не даст сделать релиз. И я выше уже упоминал, что не слишком уж хорошо, что это не часть компилятора.

feofan ★★★★★
()
Ответ на: комментарий от khrundel

Если забить на традиции, исключения - это всего лишь ещё один способ выйти из функции и передать значение.

Не совсем так. Исключение это способ сделать goto в выделенное место для обработки ошибок где-то выше по стеку.

Непроверяемые исключения - это что-то типа динамической типизации, как в каком-нибудь js, возвращаем непонятную хрень и попробуй разберись. Также как в динамической типизации, непроверяемые исключения удобней, появилась необходимость вернуть что-то другое - возвращаешь и не надо по всему стеку вызовов параметры менять. Но и, как в динамической языке, за такое удобство платится надёжностью. Но есть одно различие: основной путь исполнения тестируется чаще, если какая функция вместо числа отдаст массив, то при отладке на такой случай почти наверняка наткнёшься, а вот проблемы времени исполнения встречаются реже и тесты на них писать сложнее. Соответственно, непроверяемые исключения убирают контроль компилятора с самых непротестированных частей.

Это всё понятно, это теория. Но на практике есть ряд ситуаций, с которыми по крайней мере дизайнеры Java не справились. Простейший пример: что делать с функцией forEach? У неё блок может кидать исключение, может не кидать, мы про это не знаем. Нужно обобщение (generic) по типу исключения, такого механизма в Java нет. Что делать, когда функция начинает выкидывать наверх десятки разных исключений? Зачем нужен такой контроль? Мы пишем интерфейс (или базовый класс). Какие исключения он может бросать? Что если в наследние понадобится бросить другое исключение? Заворачивать его (и терять весь смысл всей этой типизации)? Менять сигнатуру базового класса и переписывать весь код, который пользовался этим базовым классом? При том, что этому коду в 99% случаев не надо будет обрабатывать это исключение, ему достаточно будет его пробросить наверх. Писать 99% кода ради 1% случаев?

Ты правильно говоришь, что есть надёжность, есть удобство. И на практике ни то ни другое не возводится в абсолют, почти никто не пишет код в стиле NASA по 1 строчке в месяц, чтобы иметь 1 баг на миллион строк, людям нужно достаточное удобство при достаточной надёжности.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

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

Joe_Bishop
()
Последнее исправление: Joe_Bishop (всего исправлений: 1)
Ответ на: комментарий от feofan

К слову, основной недостаток растовской обработки ошибок - это обратная совместимость при exhaustive check. Как только я добавляю новый тип ошибки - у всех ломается сборка.

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

RazrFalcon ★★★★★
()
Ответ на: комментарий от feofan

Посмотри rust, подход к обработке ошибок мне очень нравится.

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

Далеко не всегда есть только два варианта.

Ну так если ты можешь обработать ошибку, возьми и обработай её, в чём проблемы-то. Тебе исключения как-то мешают что ли. Вопрос в том, что делать с 99% случаев, когда ошибку обработать никак нельзя. И на этот вопрос исключения и коды возврата отвечают по-разному. Когда понятно, как обрабатывать ошибку, тут ничего интересного нет, берёшь и обрабатываешь, там и там это делается одинаково.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от Legioner

Классические три подхода обработки ошибок(как в том баянистов диалоге abort/retry/ignore) 1)пришла ошибка сконвертили в исключение/пробросили ее дальше 2) пришла ошибка поправили параметры вызова/чуть поменяли окружение вызвали ещё раз 3) вывели в лог(или не вывели) и забили

lberserq
()
Ответ на: комментарий от NextGenenration

Я правильно понимаю что теперь пользователям придётся писать кучу кода для уточнения типа?

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

feofan ★★★★★
()
Ответ на: комментарий от Legioner

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

RazrFalcon ★★★★★
()
Ответ на: комментарий от Joe_Bishop

именно поэтому в Го нет их поддержки на уровне языка

Их там нет потому, что ЦА - одноклеточные.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

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

А коды возврата тебе как помогут? Раньше у тебя было if err != null { return err; } и этот код так же будет падать, или что там у тебя прописано сверху. Или ты про Checked исключения? Ну тут палка о двух концах. Если я обновляюсь и мне надо переписывать код, скорее всего я такую библиотеку в тот же день выкину из проекта, никто так не делает, если речь не идёт о мажорном релизе. Поэтому библиотеке по-любому надо как-то по-другому доносить эту информацию до разработчика. Я не против checked исключений, но пока их нигде нормально не сделали.

Legioner ★★★★★
()
Ответ на: комментарий от RazrFalcon

Таки предлагаете отказаться от 99% пользователей?

Предлагаю образовывать 99% пользователей, а не потакать им.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

В любом случае преимущество вижу только в скорости

Суть не в скорости. А в «ручной» обработке. Компилятору видно что и откуда приходит и программисту видно кто и что бросает.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

Продолжать работать в непредвиденной ситуации это неправильная работа.

Можно пример такой ситуации?

connection.prepareStatement(sql) возвращает ошибку.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Самая бредовая аргументация за исключения, что я видел.

RazrFalcon ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.