Pull to refresh

Comments 95

Честно говоря, не очень понимаю, каким образом человек от того, что «NewObject» идет в базу, человек опять пришел к идее того, что надо везде всё передавать явно :)? Функцию, которая достает Object из базы, надо просто назвать GetObject, и всё.

Чтобы писать тесты и создавать моки, достаточно изолировать лишь небольшую часть зависимостей. Например, если функция скачивает что-то из интернета по HTTP, достаточно сделать конфигурируемым URL, куда она идет. После этого вы создаете тестовый HTTP-сервер и легко тестируете этот код.

То же самое с методом NewObject — я всегда сам был сторонником чистых юнит-тестов (хотя бы из-за того, что они быстрые), но всё же, практика показывает, что намного лучше всё же не пытаться мокать базу, а разрешать коду работать с какой-нибудь временной базой — иначе «протестированный» код на самом деле может и не работать, и вы можете об этом узнать слишком поздно.
Честно говоря, не очень понимаю, каким образом человек от того, что «NewObject» идет в базу, человек опять пришел к идее того, что надо везде всё передавать явно :)? Функцию, которая достает Object из базы, надо просто назвать GetObject, и всё.
Ну да. Если есть объект DB, у которого есть метод GetObject() — то тут никакой магии нет. В статье не описано, но как я понимаю — если мы говорим не о функции, а о методе объекта, то свойства объекта уже явно несут информацию о (возможном) поведении.

В случае же с функцией конструктором — да, я с автором согласен :)


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

После этого вы создаете тестовый HTTP-сервер и легко тестируете этот код.

Зачем писать функциональный тест, если для вашего примера unit будет хватать?


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

Если тестируется именно взаимодействие с БД — вполне резонно, репозитории например. Если тестируется что-то использующее репозитории — базу дергать в абсолютном большинсве случае будет плохой идеей.

Насколько я понимаю по линку расскзывают что такое DI и как его реализовать на Go руками. Я видимо неправильно задал вопрос. Мне интересно есть ли в Go средства для автоматизации DI. Что-то эквивалентное Spring или Guice в java.

есть пакет https://godoc.org/github.com/facebookgo/inject

У меня создаётся впечатление, что вы поняли мой вопрос правильно :).
Получается, что если я описываю в коде, например, дом, со всеми его компонентами включая дверные ручки, то нужно прямо из функции main передать созданные объекты типа "ручка" в то, что делает дом и потом там внутри дома передавать эти объекты в каждый конструктор. И всё это для того, чтобы можно было передать ручку в конструктор двери.

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

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

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


В такой интерпретации тут грех не сказать про то, что если ручки отличаются только свойствами, то в Go сам собой просится сделать ручку интерфейсным типом. Что-то вроде:


type Knob interface {
    OpenDoor() error
}

Тип описывает поведение и дверь работает с ручкой как с объектом, поведение которого она знает:


type WoodenKnob struct {}
func NewWoodenKnob() *WoodenKnob { return &WoodenKnob{} }
func (*WoodenKnob) OpenDoor() error { return nil } // satisfies Knob interface
...
knob := NewWoodenKnob() // returns static type WoodenKnob
door := NewDoor(knob) // NewDoor expects interface Knob as a paramter

и какая там ручка на самом деле, деревянная или хрустальная — это уже дереву по барабану, до тех пор пока она удовлетворяет интерфейсу (а это известно на этапе компиляции).

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

Теперь у вас ответственность за знание о ручке переместилась из двери в какой-то другой класс, который двери делает.
С этого надо начинать — кто владеет информацией о том, где какая ручка?
С этого надо начинать — кто владеет информацией о том, где какая ручка?

Удобно такие вещи вообще в конфигурации задавать. Особенно это удобно для тестов.

Удобно такие вещи вообще в конфигурации задавать. Особенно это удобно для тестов.

Опять же — магия. Глядя на код, непонятно, что с кем работает.


Гораздо удобнее, взглянув на код теста увидеть что-то вроде:


   knob := &MockedKnob{}
   door := NewDoor(knob)
   // run door tests

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

ИМХО удобно иметь конфигуратор в продакшне и моки в тестах. Я разделяю ваше мнение, что удобно, когда всё явно. Но такой подход часто порождает большое количество явных параметров, которые класс сам не использует, а просто прокидывает непонятно кому. Для этого прокидывания тоже надо писать явный код. И это тяжело.

Это действительно может быть проблемой, если писать код на Go в стиле класс-ориентированных языков. В Go очень редко можно увидеть проекты, в которых "иерархия" выходит за рамки 4-5 уровней вложенности. Embedding, интерфейсы, удобная CSP коммуникация позволяет строить сложные архитектуры без бесконечных уровней вложенности. Возможно я ещё что-то упускаю, но вот описанной вами беды, которую я регулярно видел в С++ проектах, в Go я не наблюдаю.

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

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

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

Да, собственно выбор между двумя вариантами — использовать глобальный стейт или передавать каждому уровню абстракции.

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

Тоже глобальный стейт, конечно, но не засоряет код

А засоряет другое место (конфиг DI), магически меняя код. Всё то, что в Go любят :)


За ссылку спасибо.

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


С другой стороны требовать применения правил, когда явных ограничений нет — бессмысленно.
Заставлять программиста придерживаться строгой чистоты в коде как парадигмы можно сколько угодно, но без кнута в виде компилятора/линтера, которые будут контролировать программиста просто бессмысленно.


Функционал контроля чистоты можно вывести в специальные директивы компилятора, в итоге язык выиграет в надежности, но потеряет в простоте, это выливается в вопрос "что важнее?".


Я не спорю, что практики описанные в статье имеют свои преимущества, но применять повсеместно их конечно никто не будет.

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

Вот с одной стороны, я с этим утверждением согласен. С другой стороны, есть такое понятие как негласные соглашения и паттерны использования, которые начинаются в самом коде стандартной библиотеке Go, расползаются по туториалам, open-source кодовым базам и тд.


Вот взять, к примеру, тот же способ делать конструкторы (которые, вобщем-то не всегда нужны, и, которые по сути, просто функции, поэтому в Go и нет специальной магии для конструкторов) — имя функции начинается с New и возвращает указатель на создаваемый тип. Этот паттерн везде, он никак не энфорсится компилятором — программист волен писать CreateObject(), ConstructObject(), изобретать велосипеды вроде (Object) Construct() Object и тд, но, почему-то все используют именно подход с New. Возможно, потому что он просто проще и понятней, а может потому что, благодаря compatibility promise, туториалы по Go остаются актуальными на много лет, и это ускоряет распространение и укрепление best practices и вот таких негласных соглашений. Интересная тема, вобщем.

но применять повсеместно их конечно никто не будет

Повсеместно, может, и не будет, но в отдельных проектах — пожалуйста :). Посмотрите на juju, например: https://github.com/juju/juju/blob/01b24551ecdf20921cf620b844ef6c2948fcc9f8/apiserver/hostkeyreporter/shim.go
Заставлять программиста придерживаться строгой чистоты в коде как парадигмы можно сколько угодно, но без кнута в виде компилятора/линтера, которые будут контролировать программиста просто бессмысленно.

Python вот как-то живет с pep8 и все норм.

Самое главное и лучшее свойство Go это то, что он, по-сути, антимагический.

Язык у которого нет комментариев (а только метаинформация) и который обладает такой ужасной фичей как "кодогенерация" не может быть антимагическим.


Для примера, вот интеграция C в GO. Это магия кодогенерации и метаинформации о функциях.

Язык у которого нет комментариев

А куда они делись? Сегодня ещё были, а, поскольку у языка promise of compatibility, не думаю, что комментарии убрали :)


Для примера, вот интеграция C в GO

cgo это не Go. Это грамотное решение, которое было нужно на первых этапах популяризации языка, когда нативных библиотек для всего на свете ещё не было.

А куда они делись? Сегодня ещё были, а, поскольку у языка promise of compatibility, не думаю, что комментарии убрали :)

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


cgo это не Go. Это грамотное решение, которое было нужно на первых этапах популяризации языка, когда нативных библиотек для всего на свете ещё не было.

Это подход от людей, которые разрабатывают Go, который ясно показывает, что комментариев в этом языке нет, только метаинформация.


В Python есть разница между этими двумя вещами, в Java для таких вещей есть аннотации, а в go просто нет комментариев.

Да, в го решили объединить. Но на самом деле комменты отличаются от директив компилятора пробелом в начале :). Другой вопрос, что это решение, скажем так, немного нестандартное :)

Точно? В том же cgo вот тут есть пробелы в начале:


// #include <stdio.h>
// #include <errno.h>
import "C"

А в примере по go generate уже нет


//go:generate go tool yacc -o gopher.go -p parser gopher.y

Иными словами, наличие проблема вряд ли спасает.

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

Каким это образом подключенная библиотека "приймет комментарии за инструкции".


Небольшой ликбез про директивы компилятора в Go:


  • директивы компилятора доступны только компилятору и статическим анализаторам кода
  • директивы компилятора в 99.9% случаев используются внутренне в коде самого Go
  • директивы компилятора в Go имеют специальный и очень явный формат //go:something
  • этих директив три с половиной штуки
  • единственная публично известная и используемая директива это //go:generate

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


Все остальное, вроде "это уже не используется", "это не нужно" и прочее — демагогия. Прецентедент есть и от него уже не отмытся. Ведь когда кровавый энтерпрайз таки придет за Go, он будет использовать самые темные, но гибкие его места, как это произошло с Python и Java.


И кстати, возможно, вы мне подскажите, как работаю такие структуры:


`inject:""`
`inject:"private"`
`inject:"dev logger"`

Это же не комментарии?

У меня есть пример одной библиотеки, которая поставлялась авторами языка — это cgo

Было бы проще, если бы вы сначала изучили тему :)
cgo это не библиотека, это изначально заложенная в язык — компилятор, тулинг, рантайм — интеграция с С.


Прецентедент есть и от него уже не отмытся.

Ну вам виднее.


Это же не комментарии?

Нет, это тэги структур :) Давайте так, вы сначала познакомитесь с темой разговора, а потом начнёте осуждать, а не наоборот.

Нет, это тэги структур :) Давайте так, вы сначала познакомитесь с темой разговора, а потом начнёте осуждать, а не наоборот.

А ничего, что я как раз это не приводил в пример?) Именно по той причине, что вы назвали.

Вот вам ответ из 2022 года - нативных библиотек для всего на свете нет до сих пор. Продолжаем пользоваться CGO.

SirEdvin
Вместо комментариев там метаинформация, доверять которой нельзя, так как никто не знает, не приймет ли ее за инструкции библиотека, которую вы подключите.


Можете объяснить что вы имеете ввиду? Потому что согласно спецификации языка комментарии таки есть — https://golang.org/ref/spec#Comments

P.S. Промахнулся…

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

Спасибо, я так понял речь об этом https://golang.org/cmd/compile/#hdr-Compiler_Directives

Помимо этого есть еще примеры, когда так интегрируют целые языки. Так же, почему-то там умолчали о таких штуках, как go generate и ряде служебных дополнительных, если не ошибаюсь.

cgo это специальный случай, который был нужен на заре языка. Раз вы пишете "целые языки", приведите пример какие ещё языки таким способом интегрируют.

На любой такой другой случай так же можно сказать "это был специальный случай". Говорить, что код на C/C++ нужен на заре языка — это как минимум немного приукрашивать. Все платформо ориентированные методы и вещи, требующие дополнительной производительности будут писатся на C/C++.


Ну а так больше интерграции с компилируемыми языками я не нашел.

Все платформо ориентированные методы и вещи, требующие дополнительной производительности будут писатся на C/C++.

не будут, уже все давно переписано на Go.
не будут, уже все давно переписано на Go.

Вы хотели сказать, уже написаны все обертки над C/C++, как например, для systray?

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


Или вы предпочитаете cherry-picking, confirmation bias и прочие логически ошибки, чтобы формировать свое видение?

Окей, я вижу вы разбираетесь в теме.


Расскажите тогда, пожалуйста, как можно реализовывать платформо-ориентированые методы, такие как работа c winapi, systray и прочими плюшками без нативных c/c++ биндов?


Я вот знаю только один способ — это через c++, или через импорт библиотек, или через связку нативных функций, если таких библиотек нет, или они тебя не устраивают.


Я что-то упустил?


Например, вот вам либа для работы с mpi: https://github.com/JohannWeging/go-mpi

Расскажите тогда, пожалуйста, как можно реализовывать платформо-ориентированые методы, такие как работа c winapi, systray и прочими плюшками без нативных c/c++ биндов?

Как уже не раз говорилось, Go был создан для бекендов, серверов, клауда и все что около. Десктопный софт, в котором приходится плясать и выкручиваться вокруг фантазий и legacy-наследия целого зоопарка разработчиков — это, мягко говоря, не ниша Go. Не говоря уже о том, что десктопный софт уже давно не в теме, и интереса к этой нише нет. Тоесть что-то, конечно делают, и в embedded Go зашел, и UI интерфейсы пытаются пилить, но это не основная ниша Go, поэтому трейдофф в виде "использовать биндинг для вот той проприетарной никому уже почти не нужной технологии", обычно вполне себе работает.

И разумеется, не один популярный проект, который повсеместно используется не использует cgo… oh wait, а как же docker?


Там куча примеров использование cgo.

Вы пытаетесь сказать, что docker использует cgo, потому что на Go мало библиотеке? Хахаха. Docker использует cgo, потому что он настолько зависит от низкоуровневого взаимодействия с системой и ядром, что у вас уши на лоб полезут, когда узнаете обо всех вызовах, с которыми сталкиваются разработчики docker-а (у меня лезли, когда знакомый из Docker-а рассказывал).


Я не понимаю, ну блин, зачем набрасывать, не разбираясь в теме. Вы от этого что, удовольствие получаете? Вам платят за это?

Небольшая шутка на тему

image


Давайте я подведу итоги нашего диалога:


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

Наша дисскусия началась с того, что в языке Go комментариев нет. Я обосновал свою позицию и привел в пример технологию, которая это доказывает и которая повсеместно используется в более-менее сложных проектах. Это используется, например, в пакете unix, который используется очень часто (docker, prometheus).


Cgo есть и вы никогда не выбросите его из самого языка, а значит, в этом языке никогда не будет комментариев.


Я не прав?

Я не прав?

Сожалею.


Вы сделали в корне ложное утверждение "в Go нет комментариев", основанное на:


а) незнании Go
б) ложных предположениях ("никто не знает, как библиотека будет использовать комментарии", хахаха)
в) сильнейшем confirmation bias-е, который сквозит через все комментарии.


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


Черт, на что я трачу свое время. Развлекайтесь дальше :)

а) Пруфы? Я не использовал знаний, которых у меня по go нет. Какие-то базовые есть, вот мне их и хватило.
Какие же знания позволят мне разглядеть то, чего нет?
б) Из опыта работы над проектом даже из 3 людей становится понятно, что довольно часто разработчики не знают всех библиотек, которые используется на проекте.
в) Потому что я показываю частные случаи. Разумеется, никто не будет на постоянной основе заниматся такой фигней, но частных случаев хватает.


И если вы не знаете, что такое комментарии, то я напомню:


Коммента́рии — пояснения к исходному тексту программы, находящиеся непосредственно внутри комментируемого кода. Синтаксис комментариев определяется языком программирования. С точки зрения компилятора или интерпретатора, комментарии — часть текста программы, не влияющая на её семантику. Комментарии не оказывают никакого влияния на результат компиляции программы или её интерпретацию. Помимо исходных текстов программ, комментарии также применяются в языках разметки и языках описания.

И вот самое главное:


Комментарии не оказывают никакого влияния на результат компиляции программы или её интерпретацию

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

тот C код не будет комментарием только тогда, когда сразу же после этого блока будет идти `import «C»`
Вот cgo:
// #include <stdio.h>
// #include <errno.h>
import "C"


Вот комментарий просто:
// #include <stdio.h>
// #include <errno.h>

import "C"

Окей, а тут значит я читал одним местом.
Спасибо)

могу сделать вывод, что вы не читали совсем, потому что это написано в самом начале доки про cgo — https://golang.org/cmd/cgo/
If the import of «C» is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package.

К сожалению, читал, но вот начиная с первого примера(


В целом, мое замечение про остуствие комментариев это не снимает, но тот факт что я зашкварился остается :(

а) см. свои комментарии выше
б) што?
в) нет, я не про ваш cherry-picking bias, я про другой — confirmation bias. у вас еще пачка логических ошибок в комментариях, но эти два самые кричащие


И если вы не знаете, что такое комментарии

Да ну, правда?


Комментарии не оказывают никакого влияния на результат компиляции программы или её интерпретацию. Как мы уже выяснили выше, "комментарии", которые задаются при помощи "//" не отвечают этому требованию.
99.999999% комментарие в Go — это просто комментарии, они никак не влияют на результат компиляции. Специальные случаи. которые очень хорошо описаны, известны, очень ограничены в использовании, позволяют статическим анализаторам извлекать из них дополнительный профит. Это не меняет того факта, что все остальные комментарии остаются комментариями.

Но раз в вашем бинарном мире это означает "в Go комментариев нет", то не буду лишать вас иллюзий. Других людей только не вводите в заблуждение.

Но раз в вашем бинарном мире это означает "в Go комментариев нет", то не буду лишать вас иллюзий. Других людей только не вводите в заблуждение.

Эм… что?


Определение комментария четкое и не дает пространства для двуяких толкований.


Комментарии должны никак не влиять на программу. Если они влияют, они не комментарии.


Бинарный мир тут не причем, я просто следую определению. Нельзя быть наполовину беременным.

#!/bin/bash

Это комментарий? Или тут тоже нет комментариев?
я имел ввиду стандартную библиотеку и рантайм — там чисто Го.
Вы выбрали специфическую область. Я не знаю про winapi и systray, но, как понимаю, винапи имеет Сишный интерфейс, потому это очевидно, что все реализации должны быть обертками надо Си. К тому же у Го свое место и это не десктопные виндовые приложения.

Если взять линуксовое апи, то Го не использует libc, у него своя реализация без C.

Вы согласны с тем, что всякие клауд штуки, типо docker — это место для Go? Там тоже куча всякий вставок с c++/c.

куча? во всем проекте вместе с вендорами С используется 47 раз.

Выкинул вендоров, итого в docker cgo используется в таких частях системы, как (судил по названиям, простите, если ошибся):


  • Обработка системных вызовов
  • Работа с примонитрованием папок
  • Абсолютно всей логики работы демона
  • Работы с оперативной памятью.

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

и почти все используется только для в специфических местах:
1. для работы под солярисом и фрибсд
2. для работы с журналд.

Кстати, я не очень разбираюсь в теме, но вот это это же екстра библиотеки?

это разрабатывается той же командой, что и язык и это часть проекта Go, иногда либы с golang.org/x/ включают в релиз языка, как случилось с context, http2.
Еще там много тулинга для Go, типа guru, golint
Нативную 0mq библиотеку не подскажите?
Или sqlite?

https://github.com/zeromq/gomq
https://github.com/iamacarpet/go-sqlite3-win64 (вызов к оригинальной .so/.dll без cgo)


Хотя с sqlite проблема в том, что sqlite по своей природе serverless, поэтому "реализация клиента" означает "переписать весь движок и поддерживать его в синхронизации с оригинальным", и учитывая объем кода (там 200 тысяч строк кода на C), и тот факт что а) для go есть пачка альтернатив embedded dbs вроде BoltDB (я использую в продакшене её, к примеру), б) cgo решение многие используют уже много лет в продакшене и никаких проблем не испытывают, сильного стимула переписывать и нет, увы.

Первое — неполная реализация.
Второе — не нативная, так как требует родной библиотеки.

Ситуация «Всё переписано на нативном го» не наступит никогда. Причём причину Вы сами написали.
Ситуация «Всё переписано на нативном го» не наступит никогда. Причём причину Вы сами написали.

Все верно. Автор выше под фразой "все уже переписано" подразумевал "всё, что востребовано и не имеет альтернатив". Вы, конечно, можете гнуть свою линию, но я варюсь в мире Go уже 4 года и компании, которые используют что-то с cgo — это единичные случаи, это настолько мизерный процент, что мне даже смешно, когда cgo пытаются представить таким вот монстром-стоппером :)

Все платформо ориентированные методы и вещи, требующие дополнительной производительности будут писатся на C/C++.

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


Ну а так больше интерграции с компилируемыми языками я не нашел.

Странно, вы же чуть выше уверяли, что "Прецентедент" был, и Go обречен.

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

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


То, что есть проекты, которые сделали это за вас — это не значит, что оно переписано на Go.


И так же, я отлично понимаю, что правильно написанная программа на C будет быстрее правильно написанной программы на Go, что бы вы не делали. Другое дело в скорости написания такой программы.


Странно, вы же чуть выше уверяли, что "Прецентедент" был, и Go обречен.

И? "обречен" — это прогноз, а не констатация факта. Я могу быть не прав, и коммьюнити окажется лучше, чем я о нем думаю и откажется от использования темной гибкости go, все могут быть неправы и "кровавый энтерпрайз" не придет за Go, потому что он ему не нужен.

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

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


и коммьюнити окажется лучше, чем я о нем думаю

Хаха. Я передам коммьюнити. Там всем очень важно ваше мнение. Как вас представить?

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

А что насчет C? Ведь абстрации все равно чего-то да стоят.

Какие абстракции? Основные потери перформанса в сравнении с сырым С это а) выделение памяти б) работа GC, но эти потери, мягко говоря, не на порядок, тот же масштаб. Memory layout в Go очень близок к С, поэтому все основные операции и манипуляции (создание объектов, вызов функций/методов и тп) опять же, генерируют код на ассемблере очень близкий к аналогичному в С… Интерфейсы и коммуникация через каналы, безусловно, несут некоторый оверхед, но снова же, это наносекунды, а не разница на порядки, как в случае с питоном или нодой.


При этом, в Go ещё достаточно места для оптимизаций, и это один из главных акцентов в каждом релизе — вот SSA бекенд появился один релиз назад и только этим добавил +15% сырого перформанса, хотя весь его потенциал ещё не задействован.


Ну а правда в том, что 80% современного бекенд программирования не требует того перформанса, который даёт Go. Именно поэтому люди продолжают писать бекенды на более медленных решениях, и ничего, живут. Но там где нужен перформанс, и при этом отсутствие мозговыносительства С++ или Rust, Go это оптимальный выбор.

там где нужен перформанс, и при этом отсутствие мозговыносительства С++ или Rust, Go это оптимальный выбор.

То есть у нас тут только выбор между мозговыносительством C++/Rust и Go. Понятно, спасибо.

А что насчет C? Ведь абстрации все равно чего-то да стоят.

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

Накладные расходы на всякие интерфейсы и прочее куда-то делись? Понятное дело, что это в целом капля в море, но они есть.


Нативный код не панацея.

и чего же стоят интерфейсы в Go?

Думаю, тут нужно проводить нормальное исследование)

Так их миллион, и их легко провести самому — бенчмаркинг встроенный в Go. Как бы было проще, если бы вы сначала изучали вопрос, а потом набрасывали. Всем бы нервы и время сэкономили.

О да, ведь бенчмарк это такое релевантное исследование. И причем именно в том, сколько стоят интерфейсы.

Порелевантнее мнения анонимуса, который не знает, как они устроены, не видел цифр, но считает это достаточным, чтобы что-то доказывать и набрасывать :)

Учитывая, что бенчмарки делаются непонятно как, непонятно чем и непонятно что меряют (и делаются, кстати, такими же анонимусами), то вы ошибаетесь.

Так это вам непонятно, потому что вы не потрудились узнать. Остальным понятно. Учите матчасть.

Я гошник и люблю го, но интерфейсы стоят дорого, весьма дорого, поэтому с месяц стоит issue на оптимизацию itab
да, дорого стоят. Но опять же — это удобства за которые нужно платить.
Можно и без них код писать.

А что за оптимизация, поделитесь ссылкой :)

Да, конечно. Там очень интересное обсуждение и код.

Круто, спасибо. Справедливости ради, там специфический кейс, у них 30000 автосгенерированных proto.Message интерфейсов.

отсутствие глобальных переменных в пакетах

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


var ErrNotFound := errors.New("not found")
var ErrInvalidRequest := errors.New("invalid request")

И тогда вызывающий может легко понимать что за ошибка была возвращена и действовать в зависимости от типа ошибки.

Там Dave Cheney всё предусмотрел и предлагает делать константы ошибок вместо переменных (основная претензия именно к возможности любого другого кода эти переменные случайно или специально модифицировать): https://dave.cheney.net/2016/04/07/constant-errors

Sign up to leave a comment.

Articles