Комментарии 41
Радует, что Go развивается, да и сообщество гоферов (в том числе и у нас) растет. Честно говоря еще пару лет назад думал, что язык наполовину мертв.
+2
Кстати, есть ли в России организации, ведущие разработку на Go, если не всю, то хотя бы частично?
Язык очень красивый, рад за него всем сердцем. Эй, с днём рождения, Go!
Язык очень красивый, рад за него всем сердцем. Эй, с днём рождения, Go!
0
Конечно есть, например Яндекс использует его для бэкэнда своего браузера.
0
Мы частично используем (компания «Системы документооборота», система документооборота «Практика»).
+3
У нас (lori.ru) некоторое количество мелких сервисов на Го. В частности, сервисы, обрабатывающие картинки. Правда, к сожалению, родная картиночная библиотека Го очень медленная, приходится использовать биндинг к ImageMagick.
Думаю, его много где используют, просто в России не очень принято делиться/хвастаться внутренними разработками.
Вообще, язык классный, очень легко на нём писать, и результат получается весьма надёжным. Хотя генериков и не хватает:)
Думаю, его много где используют, просто в России не очень принято делиться/хвастаться внутренними разработками.
Вообще, язык классный, очень легко на нём писать, и результат получается весьма надёжным. Хотя генериков и не хватает:)
0
Badoo активно использует Go. И мучается с GC…
0
опередили с новинками в 1.4
если позволите пару комментариев и дополнений:
— не многопоточный, а параллельно выполняющийся, он планируется в 1 потоке, также для этого в 1.4 запись всех указателей сделали через внутреннюю функцию, которая может эту самую запись блокировать по желанию GC
— Большая часть runtime была переписана на Go, это позволило уменьшить размер кучи от 10% до 30% за счет работы сборщика мусора, а для каждой горутины в 4 раза уменьшить начальный размер стека (с 8192 до 2048 байт), правда к релизу это значение может быть установлено в 4096 байт (имхо так и будет, все таки размер страницы памяти на большинстве систем по умолчанию именно такой)
— приватные пакеты — теперь можно создать пакет который не будет являться частью публичного api, например пакет src/mypkg/internal/foo будет доступен только для пакета src/mypkg. Пока это изменение доступно только для стандартной библиотеки языка, а для сторонних пакетов обещают включить в 1.5
— для стандартизации кодогенерации добавлена команда go generate. При помощи специальных комментариев вы можете указать какие команды необходимо запускать. Но делать как и раньше это придется руками и сохранять созданные файлы в репозиторий пакета (отсутствие автоматического запуска сделано намеренно)
— каноническое название пакета, теперь с помощью комментария рядом с названием пакета можно указать правильный вариант импорта пакета, это поможет избегать дублирования если пакеты импортируются с разными путями (например github.com/my/pkg и my/pkg)
+ несколько изменений поменьше, подробнее Go 1.4 Release Notes (англ.)
если позволите пару комментариев и дополнений:
— не многопоточный, а параллельно выполняющийся, он планируется в 1 потоке, также для этого в 1.4 запись всех указателей сделали через внутреннюю функцию, которая может эту самую запись блокировать по желанию GC
— Большая часть runtime была переписана на Go, это позволило уменьшить размер кучи от 10% до 30% за счет работы сборщика мусора, а для каждой горутины в 4 раза уменьшить начальный размер стека (с 8192 до 2048 байт), правда к релизу это значение может быть установлено в 4096 байт (имхо так и будет, все таки размер страницы памяти на большинстве систем по умолчанию именно такой)
— приватные пакеты — теперь можно создать пакет который не будет являться частью публичного api, например пакет src/mypkg/internal/foo будет доступен только для пакета src/mypkg. Пока это изменение доступно только для стандартной библиотеки языка, а для сторонних пакетов обещают включить в 1.5
— для стандартизации кодогенерации добавлена команда go generate. При помощи специальных комментариев вы можете указать какие команды необходимо запускать. Но делать как и раньше это придется руками и сохранять созданные файлы в репозиторий пакета (отсутствие автоматического запуска сделано намеренно)
— каноническое название пакета, теперь с помощью комментария рядом с названием пакета можно указать правильный вариант импорта пакета, это поможет избегать дублирования если пакеты импортируются с разными путями (например github.com/my/pkg и my/pkg)
package pdf // import "rsc.io/pdf"
+ несколько изменений поменьше, подробнее Go 1.4 Release Notes (англ.)
+11
Чисто гипотетически, реально ли на Go переписать Андроид? Слышал, что у гугла были проблемы с ораклом из-за джавы, да и вроде Go рассчитан на многопроцессорную архитектуру, к коим устремлены современные смарты.Вроде как ништяк получился бы. Объясните неспециалисту
+2
Переписать весь Android это вряд ли, тем более что он написан не на Java. А вот приложения вы можете уже сейчас писать на C/C++ с помощью Android NDK. В Go 1.4 должна появиться поддержка Android NDK, так что можно будет начинать его потихоньку использовать.
0
java (dalvik) это платформонезависимый байт код, который выполнится на любом устройстве, в Go нет виртуальной машины и придется создавать исполняемые файл под все платформы (процессоры). Уже есть много софта который написан на java. Ну и грузить все ядра на мобильнике — это только для игрушек и бенчмарков. Так что Go и Java для разного, а вот рассматривать Go как язык для 3D игр очень даже. По сути по скорости он проигрывает C в обработке бинарных данных (например декодирование изображений 2-3 раза) из-за того что все операции в GO проверяются (границы массива и т.п.) и если вы в это упретесь всегда можно написать часть кода на C
0
НЛО прилетело и опубликовало эту надпись здесь
Поздравляю! Ура!
\(^-^)/
\(^-^)/
+2
Мысли вслух
Хейтеры, как правило, к основным недостаткам Go относят отсутствие генериков и обработка ошибок.
Вот лично мне генериков не хватает, так как interface{} все-таки не такой шустрый как хотелось бы, а ошибки — ну, жить вполне себе можно с тем, как сделано сейчас.
К альтернативам относят Rust и OCaml. Первый не пробовал, на втором мне достаточно сложно писать. Честно пытался, прочитал книгу, все равно не цепляет, как основной язык разработки
Хейтеры, как правило, к основным недостаткам Go относят отсутствие генериков и обработка ошибок.
Вот лично мне генериков не хватает, так как interface{} все-таки не такой шустрый как хотелось бы, а ошибки — ну, жить вполне себе можно с тем, как сделано сейчас.
К альтернативам относят Rust и OCaml. Первый не пробовал, на втором мне достаточно сложно писать. Честно пытался, прочитал книгу, все равно не цепляет, как основной язык разработки
0
Как адепта всяких хаскеллей, для меня тоже раньше было краеугольпым камнем отсутствие генериков. Но потом я понял, что в языке комфортнее всего, когда есть некий компромисс, между строгим статическим и абсолютным динамическим. Поиск этого компромисса — не простая задача для тех, кто стал на путь дизайна новых языков.
Мысли вслух
Мысли вслух
0
в Rust также нет исключений, из плюсов там есть макрос ifError, тоесть
и я бы не сказал что обработка ошибок в go уж так плоха, у нее есть свои плюсы, если например кто-то наплевал на обработку ошибки, это будет видно во многих случаях. (ну и методы в которых можно ожидать ошибку тоже видно)
а по поводу interface{} — если не секрет, что вы делали что ощутили «не шустрость»?,
в моих кейсах например вместо container/list сделать свой (с указателем вместо Value interface{}) то выигрыш от отказа от интерфейса получается порядка 10-7 на операцию вставки (на получении чуть меньше). т.е. на 10кк элементах выигрыш 1 секунда.
// вместо
if err != nil {
return err
}
// такое
ifError(err)
и я бы не сказал что обработка ошибок в go уж так плоха, у нее есть свои плюсы, если например кто-то наплевал на обработку ошибки, это будет видно во многих случаях. (ну и методы в которых можно ожидать ошибку тоже видно)
а по поводу interface{} — если не секрет, что вы делали что ощутили «не шустрость»?,
в моих кейсах например вместо container/list сделать свой (с указателем вместо Value interface{}) то выигрыш от отказа от интерфейса получается порядка 10-7 на операцию вставки (на получении чуть меньше). т.е. на 10кк элементах выигрыш 1 секунда.
0
Не нашел никаких упоминаний макроса ifError в Rust. Вероятно его убрали.
Отличия обработки ошибок в Go и Rust состоят в основном в том, что в Rust есть Pattern matching + стандартная функция unwarp.
Для примера возьмем функцию, которая может вернуть ошибку(в виде кортежа в случае с Go, в виде типа Option в случае Rust): конвертация строки в число.
Go:
Игнорируем ошибку:
Падение при некорректной строке
Обработка ошибки:
Rust:
Падение при некорректной строке:
Обработка:
Как в Rust совсем проигнорировать ошибку и иметь при этом возможность обратиться к переменной 'n' я не придумал.
Rust заставляет либо проверять ошибку, либо ронять поток выполнения в случае ошибки(Option.unwrap(error) делает panic!(error) в случае, если значение — None)
Go позволяет случайно(или из-за плохого стиля кодирования) пропустить обработку реальной ошибки(первый вариант) и продолжить исполнение программы на некорректных данных.
Отличия обработки ошибок в Go и Rust состоят в основном в том, что в Rust есть Pattern matching + стандартная функция unwarp.
Для примера возьмем функцию, которая может вернуть ошибку(в виде кортежа в случае с Go, в виде типа Option в случае Rust): конвертация строки в число.
Go:
Игнорируем ошибку:
n, _ := strconv.Atoi("123")
Падение при некорректной строке
n, err := strconv.Atoi("123")
if err != nil {
panic(err)
}
Обработка ошибки:
n, err := strconv.Atoi("123")
if err != nil {
...
}
Rust:
Падение при некорректной строке:
let n = from_str::<u64>("123".as_slice()).unwrap();
Обработка:
match from_str::<u64>("123".as_slice()) {
Some(n) => { ... }
None => { ... }
}
Как в Rust совсем проигнорировать ошибку и иметь при этом возможность обратиться к переменной 'n' я не придумал.
Rust заставляет либо проверять ошибку, либо ронять поток выполнения в случае ошибки(Option.unwrap(error) делает panic!(error) в случае, если значение — None)
Go позволяет случайно(или из-за плохого стиля кодирования) пропустить обработку реальной ошибки(первый вариант) и продолжить исполнение программы на некорректных данных.
+3
В смысле, «случайно»? То есть вы считаете, что можно случайно поставить запятую и подчёркивание после переменной n?
Такие вещи можно сделать только специально и это действительно сразу видно. В этом большой плюс. Потому как задачу воспитания у молодёжи best practices никто не отменял…
Такие вещи можно сделать только специально и это действительно сразу видно. В этом большой плюс. Потому как задачу воспитания у молодёжи best practices никто не отменял…
+1
это я не правильно написал — в Rust это try! (статья в тему habrahabr.ru/post/242269/)
ifError в Go у нас было в паре проектов, но так как это не макрос там как раз вариант с panic
ifError в Go у нас было в паре проектов, но так как это не макрос там как раз вариант с panic
0
Интересно, почему Rust?
Мне кажется, что у Rust совсем другая ниша, чем у Go.
Мне кажется, что у Rust совсем другая ниша, чем у Go.
0
Не так много на рынке статически типизированных, компилируемых в нативные бинарники, кроссплатформенных, да ещё и сколько-нибудь распространённых языков. Если не брать си с плюсами, то останется, по сути, только OCaml, Go и Rust.
0
Ну .net умеет компилиться теперь в бинарники. С кроссплатформенностью хуже.
Непонятно откуда требование компилиться обязательно в бинарники. Я бы ставил требования типа «удобный GUI», «нормальная производительность».
Непонятно откуда требование компилиться обязательно в бинарники. Я бы ставил требования типа «удобный GUI», «нормальная производительность».
-3
А во что ещё? Можно интерпретировать, но даже с JIT-ом интерпретация медленна (хотя вот Lua неплохо справляется). Можно создавать код для вирт. машины (Java и вся её семья), но это требует поддержки собственно виртуальной машины, нетривиальной её настройки и обычно большого кол-ва памяти. И можно компилить в бинарники, которые запускаешь, и они работают. Особенно удобны Go-бинарники в силу статической линковки — деплой сводится к копированию ровно одного файла.
Разумеется, можно убрать требование компиляции, и тогда спектр языков станет гораздо шире. Но тем, кто выбирает Go, обычно компиляция важна.
Разумеется, можно убрать требование компиляции, и тогда спектр языков станет гораздо шире. Но тем, кто выбирает Go, обычно компиляция важна.
+2
Я мало встречал людей пописавших на Go и страдающих от отсутствия generic'ов. Генерики — это модная практика, которая тем не менее имеет свои недостатки.
Я пока что не сталкивался с ситуациями когда отсутствие отсутствие генериков на Go вызывало дискомфорт.
Я пока что не сталкивался с ситуациями когда отсутствие отсутствие генериков на Go вызывало дискомфорт.
+1
Вот отличная статья Алексея Качаева про то, когда начинают быть нужны генерики: gist.github.com/kachayev/21e7fe149bc5ae0bd878 (на английском).
Они действительно нужны не всегда. Но, на мой взгляд, их отсутствие уже начинает подтормаживать развитие языка. Без генериков трудно делать достаточно сложные универсальные библиотеки, а сила языка в том числе и в богатстве библиотек.
Они действительно нужны не всегда. Но, на мой взгляд, их отсутствие уже начинает подтормаживать развитие языка. Без генериков трудно делать достаточно сложные универсальные библиотеки, а сила языка в том числе и в богатстве библиотек.
0
Это стандартная проблема, с которой я столкнулся когда делал первый подход к Go: Попытка привычки и трюки наработанные на одном языке перетащить в другой язык. При этом, как правило, неофит не пытается понять, как принято решать эту задачу в новом языке. Он просто хочет писать как ему было удобно и привычно раньше.
Promise и PubSub'ы — это суровая необходимость javascript, вызванная его принципиально асинхронной природой. Имитировать их в Go нет никакой необходимости. Понятно, что когда ты с помощью молотка, пытаешься резать торт, то получается не очень…
Когда я осваиваю новый язык, следующим этапом после изучения синтаксиса, а читаю style guide и best practices. Это очень хорошо помогает въехать в стиль разработки принятый на конкретном языке…
Promise и PubSub'ы — это суровая необходимость javascript, вызванная его принципиально асинхронной природой. Имитировать их в Go нет никакой необходимости. Понятно, что когда ты с помощью молотка, пытаешься резать торт, то получается не очень…
Когда я осваиваю новый язык, следующим этапом после изучения синтаксиса, а читаю style guide и best practices. Это очень хорошо помогает въехать в стиль разработки принятый на конкретном языке…
0
Одной из идеоматических бест-практик Го являются каналы каналов — когда мы передаём канал Б в канал А и слушаем из канала Б результат. Если внимательно посмотреть на этот паттерн, то можно увидеть обыкновенный Promise. Но нам ведь обычно не интересно передавать _только_ каналы. Нам интересно передать данные какого-то типа, и получить через обратный канал данные какого-то другого типа. А ещё и ошибки хорошо было бы получать. Сейчас это всё можно делать только через interface{} или через копипаст. Хотя передавать в канал канал для результата — это то, чем начинается каждый учебник Го, идеоматичнее паттерна и быть не может.
На PubSub Алексей там тоже сослался — о нём рассказывается непосредственно в пайковском “Advanced Go Concurrency Patterns” (http://blog.golang.org/advanced-go-concurrency-patterns). Если это не best practice, то и не знаю, что тогда best practice.
Я давно пишу на Го, и он мне очень нравится и без генериков (я без них не «страдаю»). Однако я вижу, что с генериками мы могли бы получить более мощные библиотеки.
На PubSub Алексей там тоже сослался — о нём рассказывается непосредственно в пайковском “Advanced Go Concurrency Patterns” (http://blog.golang.org/advanced-go-concurrency-patterns). Если это не best practice, то и не знаю, что тогда best practice.
Я давно пишу на Го, и он мне очень нравится и без генериков (я без них не «страдаю»). Однако я вижу, что с генериками мы могли бы получить более мощные библиотеки.
-1
сейчас никто не мешает использовать кодогенерацию для разного рода рутины (например для сериализации/десериализации) и т.п., шаблоны в Go можно делать также, далее абстрактный пример:
в библиотеке объявляете свой тип и в методах его принимаете/возвращаете, там где нужно использовать пишите:
запускаете генерацию получаете файлик с суфиксом _gen и все работает.
вот пример подобного github.com/clipperhouse/gen
в библиотеке объявляете свой тип и в методах его принимаете/возвращаете, там где нужно использовать пишите:
// `template:"github.com/user/mylib.type"`
type myType ...
запускаете генерацию получаете файлик с суфиксом _gen и все работает.
вот пример подобного github.com/clipperhouse/gen
0
Да, есть много вариантов кодогенерации (я этим вопросом интересовался). Есть даже крутая идея генериков-как-веб-вервиса:) — bouk.co/blog/idiomatic-generics-in-go/
К сожалению, это очень ограниченное решение. Простой пример: есть некая библиотека list, реализующая, скажем, типизированный список: list.List (просто для примера). Пусть теперь в _нашем_ пакете user есть тип user.User и мы хотим в нём же использовать user.List. Кодогенерацией это сделать невозможно — чтобы сгенерировать код для List, нам надо в сгенерированный пакет импортировать пакет user, а потом то что получилось импортировать в user же. Получится циклический импорт.
К сожалению, это очень ограниченное решение. Простой пример: есть некая библиотека list, реализующая, скажем, типизированный список: list.List (просто для примера). Пусть теперь в _нашем_ пакете user есть тип user.User и мы хотим в нём же использовать user.List. Кодогенерацией это сделать невозможно — чтобы сгенерировать код для List, нам надо в сгенерированный пакет импортировать пакет user, а потом то что получилось импортировать в user же. Получится циклический импорт.
0
(сорри, в первом варианте комментария парсер съел угловые скобки)
…Простой пример: есть некая библиотека list, реализующая, скажем, типизированный список: list.List[T] (просто для примера). Пусть теперь в _нашем_ пакете user есть тип user.User и мы хотим в нём же использовать user.List[user.User]. Кодогенерацией это сделать невозможно — чтобы сгенерировать код для List[User], нам надо в сгенерированный пакет импортировать пакет user, а потом то что получилось импортировать в user же. Получится циклический импорт.
…Простой пример: есть некая библиотека list, реализующая, скажем, типизированный список: list.List[T] (просто для примера). Пусть теперь в _нашем_ пакете user есть тип user.User и мы хотим в нём же использовать user.List[user.User]. Кодогенерацией это сделать невозможно — чтобы сгенерировать код для List[User], нам надо в сгенерированный пакет импортировать пакет user, а потом то что получилось импортировать в user же. Получится циклический импорт.
0
что-то я видимо не понял примера, у вас оба типа в одном пакете, вы делаете тип usersList, реализация которого выполняется генерацией кода из шаблона который в пакете list получается файлик users_list_gen.go который сохраняется в вашем пакете user. То есть это тоже самое что вы бы сделали usersList с 0, только вам код не пришлось писать
0
Сорри, пример плох тем, что List пересекается с тем, что предлагает 'gen'. Там действительно генерится один файл, и нет проблем со встраиванием в пакет.
Но если List (или какая-то другая нетривиальная структура) требует не одного файла, а целого пакета, возможно, с подпакетами и импортами снаружи — вот как в таком случае генерировать код, я не знаю…
Но если List (или какая-то другая нетривиальная структура) требует не одного файла, а целого пакета, возможно, с подпакетами и импортами снаружи — вот как в таком случае генерировать код, я не знаю…
0
Меня печалит отсутствие стабильной библиотеки для GUI. Go-qml банально []string как модель принять не может, а в go-ui вообще нет такого контрола как ComboBox. Go-gtk мало того что не развивается, так и толком скомпилить не получается…
Может посоветуете еще чего для кроссплатформенной морды?
Может посоветуете еще чего для кроссплатформенной морды?
0
wxWidgets пробовали?
0
> банально []string как модель принять не может
«Это временные трудности на пути к царству света!»
Самый адекватный хак здесь это сделать метод func At(i int) string, тогда можно будет использовать как модель длину слайса, а внутри элемента модели через .At(index) получить искомую строку. Так можно слайс любых объектов завернуть.
Если не очевидно, могу пример привести.
«Это временные трудности на пути к царству света!»
Самый адекватный хак здесь это сделать метод func At(i int) string, тогда можно будет использовать как модель длину слайса, а внутри элемента модели через .At(index) получить искомую строку. Так можно слайс любых объектов завернуть.
Если не очевидно, могу пример привести.
0
Да, пожалуйста. То есть я понял, что надо воспроизвести методы, которые qml ждет от модели и которых нету у слайса, но мне казалось, что оно падало в момент присвоения прям с каким-то мессагом типа «connect with developers»
0
Нет, там никто не ждет методы, вот пример с делегатом github.com/go-qml/qml/tree/v1/examples/modelview/delegate
то же самое, когда вы делаете Component для ListView.
то же самое, когда вы делаете Component для ListView.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Go исполнилось 5 лет