Go: 10 лет и растём дальше

https://commandcenter.blogspot.com.es/2017/09/go-ten-years-and-climbing.html
  • Перевод

На этой неделе мы отмечаем 10-летнюю годовщину создания Go.


Всё началось с обсуждения вечером в четверг, 20 сентября 2007. Оно привело к организованной встрече между Робертом Грисмайером, Робом Пайком и Кеном Томпсоном в 2 часа дня на следующий день в конференс-руме Yaounde в Здании 43 главного кампуса Google Mountain View. Название для языка появилось 25-го числа, несколько сообщений спустя после начала переписки о дизайне:


Тема: Re: обсуждение языка программирования 
От: Роб 'Коммандер' Пайк 
Дата: Вт, Сен 25, 2007 в 3:12 PM
Кому: Роберт Грисмайер, Кен Томпсон    

у меня появилась пара мыслей по этому поводу на пути домой.

1. имя

'go'. можно найти оправдания для такого имени, но у него очень хорошие свойства.
оно короткое, легко печатать, например: goc, gol, goa. если будет интерактивный 
дебаггер/интерпретатор, он может быть просто назван 'go'. расширение файла .go
...

(Следует отметить, что язык называется Go; "golang" происходит от названия сайта (go.com был уже занят компанией Disney), но это не есть правильное название языка)


Днем Рождения проекта Go официально является 10 ноября 2009 — день, когда проект был открыт open-source миру, сначала на code.google.com, перед тем как мигрировал на Github несколько лет позднее. Но сейчас давайте считать дату рождения от фактического рождения языка, двумя годами ранее, что позволит нам заглянуть глубже в прошлое, увидеть более полную картину и стать свидетелями некоторых более ранних событий из истории Go.


Первым большим сюрпризом в разработке Go было получение вот этого письма:


Тема: Фронтенд gcc для Go
От: Ян Ленс Тэйлор 
Дата: Сб, Июнь 7, 2008 в 7:06 PM
Кому: Роберт Грисмайер, Роб Пайк, Кен Томпсон

Один из моих коллег показал мне http://.../go_lang.html .
Выглядит очень интересным языком и я сделал gcc фронтенд
к нему. Понятно, там ещё много чего не хватает, но он может
скомпилировать код для решета Эратосфена с главной страницы.

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


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


Расс Кокс присоединился к зарождающейся команде Go тоже в 2008-м, принеся массу свежих трюков с собой. Расс открыл — и это именно подходящее слово — что обобщённая природа методов в Go означает, что функции тоже могут иметь методы, что привело к появлению http.HandlerFunc, что было очень неожиданно для нас всех. Расс родил и другие интересные идеи, вроде io.Reader и io.Writer интерфейсов, которые сформировали структуру всех I/O библиотек.


Джини Ким, которая была нашим продакт менеджером вначале, наняла специалиста по безопасности Адама Лангли, чтобы помочь нам запустить Go в мир. Адам сделал огромное количество вещей, которые не сильно широко известны, включая создание первой версии сайта golang.org и дашборда сборки, но, конечно, главным его вкладом были криптографические библиотеки. Поначалу они казались непропорционально большими и по размеру и по сложности, по крайней мере для многих из нас, но они стали фундаментом для столь большого количества сетевого и криптографического кода, что стали ключевой частью истории Go. Сетевые инфраструктурные компании вроде Cloudflare зависят очень сильно от работ Адама в Go, и интернет благодаря им стал лучше. Равно как и Go, за что огромная благодарность Адаму.


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


Роль Go в облачной экосистеме на самом деле даже больше. В марте 2014 Donnie Berkholz, в статье для RedMonk, написал, что Go был "появляющимся языком для облачной инфраструктуры". Примерно в тоже время Derek Collision из Apcera указал, что Go был уже языком для облака. Это могло быть ещё не так истинно в те дни, но как слово "появляющийся" и указывало, это становилось всё более истинно.


Сегодня Go это язык для софта в облаке, и одна мысль о том, что язык, которому всего 10 лет, стал доминирующим в такой большой и быстрорастущей индустрии это успех, о котором можно только мечтать. И если вам кажется, что "доминирует" это слишком сильное слово, посмотрите на интернет внутри Китая. Какое то время, высокая популярность Go в Китае, показываемая Google trends намекала на какую-то ошибку, но каждый, кто был хоть раз на Go конференциях в Китае, понимает, что эта популярность реальна. Go невероятно популярен в Китае.


Если кратко, то за 10 лет пути с Go мы прошли много ключевых точек. Одна из самых поразительных в нашем текущем положении — скромная оценка указывает, что в мире примерно пол миллиона Go программистов. Когда первое письмо с предложением имени Go было отправлено, мысль о том, что вскоре будет пол миллиона гоферов показалась бы абсурдом. И вот мы тут, и это количество продолжает только расти.


Говоря о гоферах, это было забавно наблюдать, как идея маскота Рене Френч — гофер Go — стала не только самым излюбленным созданием, но и символом Go программистов по всему миру. Многие из крупнейших Go конференций называются GopherCons, так как собирают гоферов со всего мира.


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


Оглядываясь на 10 лет назад дизайна и разработки Go, отдельно поражает рост Go сообщества. Количество конференций и митапов, длинный и всё увеличивающийся список людей, участвующих в разработке Go, изобилие open source репозиториев с Go кодом, количество компаний, использующих Go, некоторые из которых используют исключительно Go: это просто изумительно наблюдать.


Для нас троих, Роберта, Роба и Кена, которые просто хотели сделать наши программисткие будни чуть легче, доставляет невероятное удовольствие наблюдать, что наш проект запустил в жизнь.


Что принесут следующие 10 лет?


  • Роб Пайк, с Робертом Грисмайером и Кеном Томпсоном
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 287
  • –8

    "у меня возникло пару мыслей"… ндэ...

    • –2
      Спасибо за благодарность за проделанный перевод и вежливое указание на опечатку в приватном сообщении.
      • –15
        Спасибо за благодарность за проделанный перевод

        Так вы не удовольствия ради это делаете? Ну что ж: низкий поклон Вам за проделанную работу.


        и вежливое указание на опечатку в приватном сообщении.

        Стесняетесь собственных ошибок? А я даже не знал, что есть какие-то там сообщения. В свою очередь, позвольте Вас поблагодарить за все хорошее.

    • +1
      природа методов в Go означает, что функции тоже могут иметь методы

      Что это значит? Не структуры ли данных могут иметь методы?
      и интернет благодаря ним стал лучше

      им.
      • +1
        Что это значит? Не структуры ли данных могут иметь методы?

        Из спецификации языка:


        A type may have a method set associated with it.

        Вот пример https://play.golang.org/p/9ouVP44MHl
        Ну или упомянутый в статье http.HandlerFunc

        • +1
          A type may have a method set associated with it.

          И каким образом это соответствует вашему
          функции тоже могут иметь методы

          ?
          Это как раз соответствует моему
          структуры данных могут иметь методы
          • +3
            И каким образом это соответствует вашему. Это как раз соответствует моему

            В Go есть не только структуры, но и другие типы — базовые типы, массивы, слайсы, функции, мапы(map), указатели, каналы. На любой из них можно повесить свой метод (через type MyType map/chan/func.... понятное дело).

            • 0
              В Go есть не только структуры

              Под «структуры данных» я не имел в виду конкретно структуры ака записи. Скорее сложные типы данных, просто выразился неточно.
              функции, мапы(map), указатели, каналы. На любой из них можно повесить свой метод

              Имеется в виду функциональный тип, когда передается ссылка(указатель) на функцию? Тогда понятно; но все равно это не будет «функция может иметь метод». Функция в таком случае — это не тип данных, типом данных будет нечто, ссылающееся на функцию, а не она сама. Нет?
              • 0
                когда передается ссылка(указатель) на функцию

                Не очень понимаю, что вы под этим понимаете. Куда передаётся?


                Если вы пишете:


                type MyType func() bool

                то MyType это именно тип — вы можете его засовывать в другие типы, создавать переменные этого типа, присваивать их, передавать по каналам и тд.

                • 0
                  Да, верно, но это не функция. Это, как раньше называли, функциональный тип данных.
                  Функция — это коробка, которая выполняет работу, она не является типом данных. Так же, как не является т.д., скажем, оператор.
                  Но вы можете создать тип данных, который указывает на функцию с вот такой-то сигнатурой, что и сделано строкой
                  type MyType func() bool

                  ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D1%82%D0%B8%D0%BF
                  • –3

                    А с сигнатурой


                    type MyType string

                    тип указывает на строку в вашей терминологии?


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

                    • 0
                      А с сигнатурой

                      Слово «сигнатура» мною было применено к функции, «функция с такой-то сигнатурой» — т.е. набором параметров и типом (пами) возвращаемых значений.
                      тип указывает на строку в вашей терминологии?

                      Вы путаете тип данных и конкретное значение. Функция — это значение.
                      type MyType string
                      описывает тип данных «строка», и переменная такого типа может принимать разные значения — конкретные строки.
                      type MyType func() bool
                      описывает функциональный тип данных, и переменная такого типа может принимать разные значения — конкретные функции (технически — ссылки на функции, но это только деталь реализации) с вот такой вот сигнатурой.

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

                      Почему своими? Есть устоявшаяся терминология, ссылку на википедию с описанием см. выше.
                      • –1
                        Вы путаете тип данных и конкретное значение.

                        Нет, не путаю.


                        технически — ссылки на функции, но это только деталь реализации

                        Откуда вы это взяли?


                        Почему своими? Есть устоявшаяся терминология, ссылку на википедию с описанием см. выше.

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

        • +11
          Тут просто сам бог велел эту картинку вставить


          10 лет непрерывных побед.
          • +4
            Правильная картинка вот :)

            image
          • +11
            Кстати, один я заметил интересную особенность, что на Go активно переходят только PHP-шнки т.е. в большинстве своем те люди, которые привыкли писать лапшеобразный код.

            Я реально слабо представляю себе кейс когда человек решит перейти с C#/Java/D/Swift на Go и сможет внятно объяснить свое решение.

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

            • +3
              я заметил интересную особенность, что на Go активно переходят только PHP-шнки

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


              Я реально слабо представляю себе кейс когда человек решит перейти с C#/Java/D/Swift

              Вы бы ещё R или Julia назвали. По моим наблюдениям, чаще переходят с C/C++, Ruby/Node.js/Python/PHP.


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

              Слово "простота" очень легко трактуется с точностью до наоборот разными людьми. Тут глупо спорить. Кто-то считает, что если учить 4 года Haskell, то потом любая программа помещается в 3 строчки и это "простота языка", но с инженерной точки зрения простота это противоположность сложности. Почитайте "Мифический человеко-месяц" Брукса, ну, или хотя бы его же "Серебрянной пули нет", там хорошо про сложность разложено.

              • –1
                >Тут глупо спорить. Кто-то считает, что если учить 4 года Haskell
                Так, стоп. Причем тут Haskell. Вопрос был в том чем Go проще C#/Java/D/Swift/Python. Можете пример показать? Ну вот допустим я в Python могу проверить вхождение так:
                if x in arr
                На D это будет:
                if (arr.canFind(x))
                На других языках тоже примерно так же.

                Вы будете утверждать, что на Go это проще делается?

                По факту больше кода, больше ошибок, дольше разработка, сложнее рефакторинг, тестирование, отладка и тд.

                Так ГДЕ Go простой??
                • +4

                  Вы путаете простоту и количество символов, и на этом строите свои представления о том, как происходит рефакторинг и тестирование в Go.


                  Так ГДЕ Go простой??

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

                  • 0
                    ошибся веткой
                    • +1
                      >Везде
                      Да ладно врать то. Вы примеры покажите чем Go проще других языков.

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

                      >и угадать, что же он попытался упаковать в те 5 символов
                      Ага, к примеру по `canFind` или `Сontains` ну совершенно не очевидно что они делают и приходится гадать.
                      • +1
                        Вы примеры покажите чем Go проще других языков.

                        Вот держите примитивный пул воркеров. Жду ваших примеров такой же простой задачи на других языках. Если ваши рассуждения верны, то это должно быть 7 строчек на всё про всё (так чтобы я смог скопировать отсюда и запустить у себя, и чтобы это было читабельно). Жду ваших примеров.


                        package main
                        
                        import (
                            "fmt"
                            "time"
                        )
                        
                        func worker(id int, jobs <-chan int, results chan<- int) {
                            for j := range jobs {
                                fmt.Println("worker", id, "started  job", j)
                                time.Sleep(time.Second)
                                fmt.Println("worker", id, "finished job", j)
                                results <- j * 2
                            }
                        }
                        
                        func main() {
                            jobs := make(chan int, 100)
                            results := make(chan int, 100)
                        
                            for w := 1; w <= 3; w++ {
                                go worker(w, jobs, results)
                            }
                        
                            for j := 1; j <= 5; j++ {
                                jobs <- j
                            }
                            close(jobs)
                        
                            for a := 1; a <= 5; a++ {
                                <-results
                            }
                        }

                        Поверьте, как только возникнет более или менее серьезная задача

                        Я пишу "более или менее серьезные задачи" на Go уже больше 4 лет, и общаюсь с огромным количеством Go программистов по всему свету, включая ребят из Google, Uber, Dropbox, Cloudflare и Docker. Мои наблюдения очень отличаются от ваших. Расскажите, пожалуйста, сколько "более или менее серьезных задач" на Go вы написали.

                        • 0
                          «Вот держите примитивный пул воркеров. Жду ваших примеров такой же простой задачи»

                          Простите, но IMHO это лукавство — вы приводите пример не простой задачи, а той, на которой Go специализируется. Давайте приведем действительно простую задачу, и посмотрим насколько проще этот код будет выглядеть на Go:
                          echo Hello>out.txt
                          • +6
                            package main
                            
                            import (
                                "io/ioutil"
                            )
                            
                            func main() {
                                ioutil.WriteFile("out.txt", []byte("Hello"), 0664)
                            }
                            
                            • +4
                              но IMHO это лукавство — вы приводите пример не простой задачи, а той, на которой Go специализируется.

                              Попросили же показать пример, где Go проще других языков.

                          • 0

                            Вот вам пример на python:


                            from multiprocessing import Pool
                            
                            def f(x):
                                return x*x
                            
                            if __name__ == '__main__':
                                with Pool(5) as p:
                                    print(p.map(f, [1, 2, 3]))

                            Куда проще?

                            • –2

                              Хаха, вы опять пришли потроллить? Код который вы написали (или скопировали из первого результата гугла, как вы это любите делать)
                              а) запускает 5(!) разных процессов
                              б) не совсем тот же, код который просили написать
                              в) не запускается :)


                              $ python main.py
                              Traceback (most recent call last):
                                File "main.py", line 7, in <module>
                                  with Pool(5) as p:
                              AttributeError: __exit__
                              • +1
                                a) И? У вас были условия на количество процессов?
                                б) «Вот держите примитивный пул воркеров» — это примитивный пул воркеров. Нет?
                                в) Потому что я скопировал этот пример из третьего питона, попробуйте на нем.

                                Если уж вам нужен примитивный пул воркеров, которые будут работать на корутинах — то так сразу нужно было и писать.
                                • 0

                                  SirEdvin ах, другая версия нужна, ну окей. Надеюсь, что вы всё же сознательно троллите — в примере на Go я спокойно могу запустить 10000 воркеров, а ваш пример на 10000 процессов положат систему.


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

                                  • +1
                                    Ну при чём тут детали реализации, когда спор был о преимуществах/недостатках синтаксиса и общепринятых практик Go и Python? Никто же не пытался доказать, что на пайтон лучше писать высокопроизводительный код, не об этом речь.
                                    А какой вообще смысл в в тысячах воркеров? Обычно число воркеров оптимизируют по производительности и оно порядка числа ядер в системе. Число тасков может быть любым.
                                    • +1

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


                                      Но всё же человек попросил написать, в чём Go проще других языков, и я привёл пример. Мне, зачем-то начали показывать костыли на других языках, которые запускают множество процессов. Давайте может ещё k8s кластер поднимем и одной строчкой на баше задеплоим пул воркеров и обсудим?


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


                                      Обычно число воркеров оптимизируют по производительности и оно порядка числа ядер в системе.

                                      Согласен. Поинт был в том, что горутины и OS процессы это разные лиги вообще.

                                    • –1
                                      SirEdvin ах, другая версия нужна, ну окей. Надеюсь, что вы всё же сознательно троллите — в примере на Go я спокойно могу запустить 10000 воркеров, а ваш пример на 10000 процессов положат систему.

                                      Внезапно, но нет. Просто программа упадет с ошибкой.


                                      Слишком много процессов
                                      Traceback (most recent call last):
                                        File "test.py", line 7, in <module>
                                          with Pool(10000) as p:
                                        File "/usr/lib/python3.6/multiprocessing/context.py", line 119, in Pool
                                          context=self.get_context())
                                        File "/usr/lib/python3.6/multiprocessing/pool.py", line 174, in __init__
                                          self._repopulate_pool()
                                        File "/usr/lib/python3.6/multiprocessing/pool.py", line 239, in _repopulate_pool
                                          w.start()
                                        File "/usr/lib/python3.6/multiprocessing/process.py", line 105, in start
                                          self._popen = self._Popen(self)
                                        File "/usr/lib/python3.6/multiprocessing/context.py", line 277, in _Popen
                                          return Popen(process_obj)
                                        File "/usr/lib/python3.6/multiprocessing/popen_fork.py", line 20, in __init__
                                          self._launch(process_obj)
                                        File "/usr/lib/python3.6/multiprocessing/popen_fork.py", line 66, in _launch
                                          parent_r, child_w = os.pipe()
                                      OSError: [Errno 24] Too many open files

                                      А уж если вам настолько сильно нужны корутины, то можете запустить вот это (только вам нужно будет установить библиотеку gevent).


                                      from gevent.pool import Pool
                                      
                                      def f(x):
                                          return x*x
                                      
                                      if __name__ == '__main__':
                                          pool_1 = Pool(10000)
                                          print(pool_1.map(f, list(range(0, 10000))))

                                      Надеюсь, вас не смущает в этом плане внешняя зависимость, ведь для golang очень часто приходится добавлять внешнею зависимость для обработки ошибок от dropbox.

                                      • 0
                                        Просто программа упадет с ошибкой.

                                        Удивительно эффективное решение вы написали.


                                        ведь для golang очень часто приходится добавлять внешнею зависимость для обработки ошибок от dropbox.

                                        Вы себе сами придумываете эти фантазии или кто-то помогает?

                                        • 0
                                          > Вы себе сами придумываете эти фантазии или кто-то помогает?

                                          Ну вот kubernetes и moby используют. traefik использует. А часть других проектов типа gin пилит для этого свои костыли. Некоторые обходятся без этого, но не все.

                                          > Удивительно эффективное решение вы написали.

                                          В первоначальном задании не было ничего о «а запустить сколько угодно воркеров». Какое тз — такое и решение.
                              • –4
                                Т.е. эта портянка и есть тот самый Go?
                                :) так а в чем профит-то?
                                Новый язык можно создавать по нескольким причинам:
                                1) just for fan! ну типа я такой крутой и вот что я могу!
                                2) вынужденная необходимость и отсутствие альтернатив
                                3) улучшить существующее положение дел
                                Чем вот это:
                                for j := 1; j <= 5; j++ {

                                Отличается от Сишного:
                                for( j = 1;j <= 5; j++) {

                                ?
                                Или вот это:
                                func worker(id int, jobs <-chan int, results chan< — int)

                                от Сишного:
                                void worker(int id, const int *jobs, int *results)

                                Тут возможно что-то не так с jobs и results, т.к. мутки со стрелочками не совсем понятны, хотя названия переменных наводят на мысли что jobs это входные данные, results — выходные.
                                • 0
                                  мутки со стрелочками не совсем понятны

                                  Дайте я вам плюсов в карму подкину, это прекрасно :D


                                  Чем вот это Отличается от Сишного:

                                  В этом была и идея, что язык не должен радикально отличаться от известной базы, чтобы облегчить вход. Большинство людей, знакомых с С, осваивают Go за одни выходные, и это big deal.

                                  • 0
                                    В этом была и идея, что язык не должен радикально отличаться от известной базы

                                    Я, конечно, извиняюсь, но по-моему, Go радикально отличается от C и C++. Даже не знаю, что там может быть общего.
                                    • +1
                                      Я, конечно, извиняюсь, но по-моему, Go радикально отличается от C и C++. Даже не знаю, что там может быть общего.

                                      Извиняю, но я даже не знаю, как можно не видеть общего между ними. Боюсь, я тут не помогу в таком случае.

                                      • –2
                                        Ну а что там вы видите общего?
                                        • 0
                                          Вы троллите, да?
                                          • 0
                                            Нет, на полном серьезе. Хочу вас понять. Что там общего с C, кроме фигурных скобок в «statement block» (это сейчас-то и к наследию C не отнесешь).

                                            То, что я вижу в Go vs C:

                                            • есть интерфейсы;
                                            • декларация переменной — порядок имени и типа противоположный;
                                            • инклудов, макросов нет;
                                            • синтаксис control statements другой;
                                            • ...


                                            Что общего с C/C++ вы нашли в Go?
                                            • +1
                                              Вот, кстати, тут человек не видит различий между C и Go вообще, наверное он объяснит: habrahabr.ru/post/338556/#comment_10434130
                                              • 0
                                                Вот, кстати, тут человек не видит различий между C и Go вообще

                                                Там речь не о различиях вообще, а о том, что Go проще, чем C.

                                                Думаю там видно, что:
                                                func worker(id int, jobs <-chan int, results chan<- int)

                                                отличается от:
                                                void worker(int id, const int *jobs, int *results)

                                                и «сишник» этот код на Go не поймет и будет спотыкаться при его написании (хотя бы из-за смены порядка указания имя/тип).
                                                • 0
                                                  … с тем же успехом я могу написать код на паскале:
                                                  function worker(id : integer; jobs : intchan; results : intchan) : boolean;

                                                  и сказать, что Go произошел от Delphi.
                                            • 0
                                              Вы троллите, да?

                                              Ответ: «и C, и Go являются тьюринг-полными языками программирования», конечно, правильный, но я хотел бы услышать что-то более конкретное.
                                  • +3
                                    Для сравнения, вот аналогичный код на C# под .NET Core 1.0

                                    using System;
                                    using System.Linq;
                                    using System.Threading;
                                    
                                    namespace Go_comparison
                                    {
                                        class Program
                                        {
                                            static void Main(string[] args)
                                            {
                                                var jobs = Enumerable.Range(1, 5);
                                    
                                                jobs.AsParallel().WithDegreeOfParallelism(3)
                                                    .Select(x =>
                                                    {
                                                        Console.WriteLine($"Starting work on iten {x}");
                                                        Thread.Sleep(1000);
                                                        Console.WriteLine($"Finished work on iten {x}");
                                    
                                                        return x * 2;
                                                    })
                                                    .ForAll(Console.WriteLine);
                                    
                                                Console.ReadLine();
                                            }
                                        }
                                    }
                                    
                                    • 0
                                      П.С. Вот онлайн фиддл, если хотите поэкспериментировать.
                                      dotnetfiddle.net/cQqT5O
                                      • +2
                                        Справедливости ради нужно отметить, что результатом на го будет бинарник в 1 мб, а в шарпе — папка с кучей дллок фреймворка на 45 мб (если мы хотим получить идентичный результат, «без зависимостей»). Сам код на C# безусловно восхитительно выглядит.
                                      • +1

                                        На Elixir:


                                        1..10000 
                                        |> Enum.map(&Task.async(fn ->
                                          IO.puts("worker #{&1} started job")
                                          :timer.sleep(1000)
                                          IO.puts("worker #{&1} finished job")
                                        end))
                                        |> Enum.map(&Task.await/1)
                                  • 0
                                    Если ваш 'arr' это мэп то так:
                                    if _, ok := arr[x]; ok {...}

                                    если же у вас там массив то в цикле проверять придется.
                                    В общем так же как в плюсах.
                                    • +4
                                      Так, тоесть вы уверяете, что запись вида:
                                      if _, ok := arr[x]; ok {...}

                                      Читается лучше чем к примеру:
                                      if (arr.canFind(x))

                                      >если же у вас там массив то в цикле проверять придется.
                                      А ну вообще прелестно! Проще некуда!

                                      Вот видите даже в каких-то стерильных условиях типа: «Если ваш 'arr' это мэп то» код на Go оказывается куда менее читабельный чем на других языках.
                                      • +1
                                        Я пришел на го с плюсов. На плюсах проверить входит ли значение в мэп приходится вот так
                                        if (arr.end() != arr.find(x)) { ... }

                                        и да, вариант на го мне нравится больше.

                                        Поиск же элемента в массиве в плюсах будет точно таким же — полный перебор всех значений в цикле.

                                        Ну и у меня встречный вопрос — как вы полагаете может быть сделана проверка вхождения элемента в контейнер без учета типа контейнера. Учтите, что массив не являетеся классом, это просто указатель, из него нельзя вызывать функций.
                                        • –3
                                          Ну если контейнер будет являться диапазоном (Range) то canFind будет с ним так же работать. Если нужно что-то другое, то ничего не мешает реализовать у контейнера свой метод Contains.

                                          Но тут то вся соль в том, что на Go нужно костыли городить уже в простых случаях.
                                          • +2
                                            Не совсем корректный пример, Ваш код на плюсах делает нечто большее. Просто проверка вхождения делается вот так:
                                            if (map.count(key) > 0) { ;; }

                                            find имеет смысл если сохранять итератор и потом его использовать для доступа к элементу — экономится один поиск по дереву. То есть это дополнительная функциональность С++, которая не всегда легко доступна в других языках, но пользоваться её не обязательно и не всегда имеет смысл.
                                      • +4

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

                                        • 0

                                          Да, я думаю, что между "выразительностью" и "понятностью, что автор имел ввиду", у Go приоритет смещён на последнее.

                                          • 0
                                            Мне кажется, это скорее не простота, а компактность. И тут палка о двух концах. Если число концепций слишком небольшое, то не остается ни одного очевидного/хорошего способа сделать что-то хоть немного нетривиальное. Зато, конечно, есть куча сомнительных способов и вся простота компактного языка улетучивается. Даже такой некомпактный язык как С++ и то временами недостаточно гибок — в новых стандартах приходится новые возможности вводить и всё ещё есть что добавить (мультиметоды к примеру).
                                      • +1

                                        Нет. Знаю порядка сотни go разработчиков. Php, C — чуть ли не в равной доле. Много perl ребят нашло себя в go. Также не редкость java, node.js, c#.

                                        • +1
                                          Я пришел из с/с++ в go. И жалею только о том, что его ещё нет в микроконтроллерах. И наверное не скоро будет. Слишком мало памяти в контроллерах.
                                          Пишем уже два года. И переходить назад вообще не хочется. Проект, кроссплатформенный. В том числе и на мобильных устройствах.
                                          Раздражает только один момент. Паника при выходе за массив или слайс. Меня бы устроила просто обработка ошибки. Сейчас приходится проверки ставить перед каждым обращением.
                                          • +1
                                            Особенно занятно читать вранье про простоту Go. Каким местом он простой? Что на нем делается проще чем на других языках? Такой бред могут нести только люди никогда в жизни ничего серьезного не писавшие. Вся эта простота (а по факту примитивность) приводит лишь к тому что на мало-мальски сложных проектах начинается дикое костылестроение т.к. в языке не оказывается каких-то элементарных синтаксических конструкций. Итогом является закономерный Го-внокод.

                                            Потому что когда кое-кто переходил с зоопарка C/C++ кода с кучей систем сборок, синтаксисов, редакций и прочего на милый уютный Golang, количество синтаксического сахара к котором стремится к нулю, люди возрадовались, потому что вдоволь наелись проблем, которые порождает слишком гибкий язык. Другое дело, что потом они рано или поздно осознают к тому, что golang порождает еще больше проблем из-за отсутствия значительных частей этого синтаксического сахара в виде кучи кривых конструкций и просто синтаксического мусора в коде в духе if err!=nil — прокинуть и поймут, что не зря раньше от этого отказались, и займутся всерьез внутренними соглашениями по коду вместо беготни по языкам.

                                            • 0
                                              Можно узнать чем именно плох if err!=nil? И почему отказались. Может в моих программа структура кода какая то выраженная, но мне наоборот удобно использование этой конструкции. Замусоривания я никакого не вижу. Ничего не пропустишь (конечно же если не ставить везде "_" ).
                                              • –1
                                                Почему нельзя сделать ее автоматической, как это сделали в пробросе ошибок в других языках?
                                                Опять же, если вам нужна более строгая система ошибок, то ничего не мешает сделать так, как это сделали в Java, что бы нужно было или указывать у метода throws с типами ошибок, которые он может возвращать или же обрабатывать их в методе.
                                                Если вас беспокоит оверхед от сохранения стека вызова — не сохраняйте его по умолчанию и дайте пользователям возможность его включать там, где нужно.

                                                Основная моя претензия к этой синтаксической конструкции — ее можно было полностью вынести в объявления функции и более того, сделать ее типизированной, что бы она давала больше информации.
                                                • 0

                                                  Отказ от эксепшенов, насколько я знаю, был продиктован скорее желанием упростить реализацию, чем какими-то соображениями синтаксиса. Дело в том, что сделать нормальные экспешены довольно сложное и муторное занятие полное компромисов, поэтому авторы решили их вообще выбросить из концепции.

                                                  • 0
                                                    То есть переложили с компилятора на программиста…
                                                    • –1

                                                      Не совсем. В Google в целом пришли к выводу, что польза от эксепшенов меньше, чем проблемы, которые они приносят. https://google.github.io/styleguide/cppguide.html#Exceptions
                                                      А в купе с идеологией языка — просто, но не проще, чем необходимо, это удачно сочиталось, да.

                                                      • +3

                                                        Извините, вы сами читали, что по вашей ссылке написано? Там как раз написано что


                                                        On their face, the benefits of using exceptions outweigh the costs, especially in new projects.

                                                        Пожалуйста, прекратите ссылаться на Google Style Guide как аргумент против исключений.

                                                        • –3

                                                          Извиняю, конечно читал. Я указал на этот документ не как "аргумент против исключений" (там есть аргументы и за, и против), а как аргумент того, что в Google не используют эксепшены, что, естественно, повлияло на выбор способ обработки ошибок в Go. Тоесть "сложность адекватной реализации" не была первопричиной. Главными причинами являются как раз те моменты, которые описаны в Cons в Google Style Guide — и они в идеологии языка Go имели больший вес.

                                                          • –2

                                                            В плюсах исключения не используют потому и только потому, что много легаси, которое в исключения хорошо не умеет.
                                                            А в го откуда легаси взялось?

                                                        • 0

                                                          Т.е. если в плюсах исключения сделаны через одно место, то их теперь везде использовать нельзя?

                                                          • –1
                                                            Т.е. если в плюсах исключения сделаны через одно место, то их теперь везде использовать нельзя?

                                                            Нет, но те минусы исключений, которые упоминаются в Go FAQ не имеют отношения к конкретной реализации в плюсах, а к самой концепции в целом.

                                                            • +1
                                                              Нет, но те минусы исключений, которые упоминаются в Go FAQ

                                                              Но ссылку вы дали не на Go FAQ, а на руководству по стилю для плюсов, где исключение и спроектированы, и реализованы, и применялись криво.
                                                              В Go есть полный эквивалент throw-catch-finally в виде panic-recover-defer. Так что концепция в целом никуда не делась, несмотря на всю критику.
                                                              Разве что про вышеупомянутую эквивалентность в блоге Golang деликатно не упоминается.

                                                              • –1

                                                                Ещё раз — ссылка была дана, чтобы показать, что некая культура "ухода от эксепшенов" уже была в Google ещё до Go. И те проблемы, который озвучены в Go FAQ как раз не относятся к реализации С++, и не касаются panic-recover-defer.


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


                                                                Только давайте не превращать этот тред в очередной спор про плюсы и минусы эксепшенов, мы все о них в курсе, надеюсь. Я лишь делаю акцент на том, что первопричина отсутствия эксепшенов в Go это не "сложность реализации", а более практические соображения.

                                                                • +1
                                                                  И те проблемы, который озвучены в Go FAQ как раз не относятся к реализации С++, и не касаются panic-recover-defer.

                                                                  В чем принципиальная разница между throw-catch-finally и panic-recover-defer?
                                                                  Почему проблемы первого варианта внезапно перестали касаться второго?


                                                                  эксепшены стимулируют:
                                                                  а) неправильно их использовать (panic/recover не используют для события "юзер не найден", это надо прям совсем удариться, чтобы так использовать)

                                                                  Не понимаю. Что именно в исключениях стимулирует ошибки, а в панике — нет?


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

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


                                                                  в) уменьшают понятность error-path кода (понятность что происходит, без прыгания по другим файлам и функциям)

                                                                  И здесь у паники никакого различия с исключениями не видно, по крайней мере лично мне.


                                                                  Я лишь делаю акцент на том, что первопричина отсутствия эксепшенов в Go это не "сложность реализации", а более практические соображения.

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

                                                                  • 0
                                                                    В чем принципиальная разница между throw-catch-finally и panic-recover-defer?

                                                                    В том что panic-recover это дополнительный способ обработки действительно критических ситуаций, а throw-catch-finally — основной и единственный.


                                                                    Что именно в исключениях стимулирует ошибки, а в панике — нет?

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


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

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


                                                                    А я делаю акцент на то, что исключения в Go есть, просто их зачем-то переименовали в panic

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

                                                                    • +5
                                                                      В том что panic-recover это дополнительный способ обработки действительно критических ситуаций, а throw-catch-finally — основной и единственный.

                                                                      Неправда. Вы сами опровергли собственный тезис, приведя ссылку на руководство по стилю программирования в плюсах. Никаким "основным и единственным" способом исключения не являются. По крайней мере для гугла, где го и придумали.


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

                                                                      "Более простой и удобный способ" с кодами ошибок и так поддерживается абсолютно везде. Это в общем-то исторически первый способ.


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

                                                                      Если надо именно падать — никакой recover не нужен. А так то же самое исключение вид сбоку — раскрутка стека с возможностью перехвата на более высоком уровне.


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

                                                                      Вы не могли указать, у кого конкретно "для обработки ошибок есть только исключения"?


                                                                      Паника это как раз "исключения здорового человека".

                                                                      То есть все разговоры про "в Go нет исключений" оказались чистым маркетингом, построенном на переименовании?

                                                                      • –3
                                                                        Неправда

                                                                        Правда. Обычно в языках в которых есть много способов сделать одно и тоже, появляются лагери сторонников того или иного подхода. Как правило, либо "мы используем эксепшены", либо "мы не используем эксепшены", как в Гугле, но "в одной функции используем, в другой не используем" — такого не происходит.


                                                                        с кодами ошибок и так поддерживается абсолютно везде.

                                                                        В Go нет кодов ошибок.


                                                                        Если надо именно падать — никакой recover не нужен.

                                                                        Есть ситуации, когда нужен. А так да, panic() чаще используется без recover().


                                                                        То есть все разговоры про "в Go нет исключений" оказались чистым маркетингом, построенном на переименовании?

                                                                        Нет. Вы зачем-то пытаетесь самого себя убедить в истинности этого утверждения, но нет.

                                                                        • +4
                                                                          Обычно в языках в которых есть много способов сделать одно и тоже, появляются лагери сторонников того или иного подхода. Как правило, либо "мы используем эксепшены", либо "мы не используем эксепшены", как в Гугле, но "в одной функции используем, в другой не используем" — такого не происходит

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


                                                                          Мало того, на хабре есть и другие иллюстрации:
                                                                          https://habrahabr.ru/post/118898/


                                                                          Для реального примера использования panic и recover смотри пакет json из стандартной библиотеки Go. Он декодирует закодированные в JSON данные с помощью набора рекурсивных функций. Когда на вход поступает неправильно сформированный JSON, парсер вызывает panic, чтобы развернуть стек к верхнему вызову, который восстанавливается после паники и возвращает подходящий код ошибки (смотри функции «error» и «unmarshal» в decode.go). Похожий пример такой техники в процедуре Compile пакета regexp. Существует соглашение, что в библиотеках Go, даже если пакет использует panic внутри, его внешнее API возвращает явные коды ошибок.

                                                                          В Go нет кодов ошибок.

                                                                          Судя по цитате выше, другие гоферы об этом не в курсе.


                                                                          Нет. Вы зачем-то пытаетесь самого себя убедить в истинности этого утверждения, но нет.

                                                                          Не понял. Вы сначала сами признали что panic — это исключения. А теперь сами же это отрицаете. Взаимоисключающие параграфы.

                                                                          • –7
                                                                            Так и в го есть два способа обработки ошибок

                                                                            Об этом я вам и говорил. Вы сами с собой спорите уже.


                                                                            Судя по цитате выше, другие гоферы об этом не в курсе.

                                                                            Вы сейчас используете чьи-то посты на хабре, чтобы продолжать называть вещи неверными именами? Окей, продолжайте называть как хотите.


                                                                            Не понял. Вы сначала сами признали что panic — это исключения. А теперь сами же это отрицаете

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

                                                                            • +2
                                                                              Окей, продолжайте называть как хотите.

                                                                              Вы уже 33 раза сказали, что я использую неверное имя. Я в 33 раз прошу — назовите верное.


                                                                              Я не успеваю следить за тем, как вы придумываете новые интерпретации своим и моим словами.

                                                                              Вы окончательно перешли от предмета дискуссии к обсуждению личности оппонента, причем без единого пруфлинка. И еще жалуетесь на каких-то "троллей". Нехорошо.

                                                                        • 0
                                                                          "Более простой и удобный способ" с кодами ошибок и так поддерживается абсолютно везде.

                                                                          Не совсем так. Конечно в Java вы тоже можете написать библиотеку, которая вместо FileNotFound будет возвращать некий код (как в C), но так не делают, ибо так не принято.


                                                                          Отсюда растут две проблемы.


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

                                                                          А вот в Go не принято кидать panic из библиотеки. Считается, что паниковать имеет права только ваше приложение. Т.е. эксепшену отведена совсем другая роль.


                                                                          Есть у такого подхода ахилесова пята. Когда все делаешь идеально, ты по идее должен захендлить все возможные экспешены и коды ошибок в каждой точке вызова. Разумеется так никто не делает. Но если в Java по дефолту исключение найдет путь наверх и вы получите трейс, то в Go возвратный код по дефолту просто замьютят и вы ничего не узнаете о ошибке.

                                                                          • +2
                                                                            так не принято

                                                                            "Так не принято" — это соглашение, а не язык, как меня здесь упорно убеждал автор статьи.
                                                                            В .NET для API библиотек принято иметь оба варианта. Приложение выбирает удобный для своей семантики.
                                                                            Но сам язык опять-таки ничего в этом плане не навязывает.

                                                                            • –5
                                                                              как меня здесь упорно убеждал автор статьи.

                                                                              Зная, что вам приходится по 33 раза одно и тоже объяснять. повторю ещё раз — автор статьи Роб Пайк, а не я.
                                                                              И я вас ни в чём не убеждал — вы сами себя в чём то убеждали, оперируя своими терминами, приписывая это мне. Не вводите людей в заблуждение.

                                                                              • 0
                                                                                В .NET для API библиотек принято иметь оба варианта.

                                                                                А как это реализуется? В смысле выбор.

                                                                                • +5

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


                                                                                  1. Метод Parse бросит исключение,
                                                                                  2. Метод TryParse вернет флаг как результат (и распарсенное как out-параметр при успехе)
                                                                                  3. Метод ParseOrDefault вернет null

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

                                                                              • +3
                                                                                Конечно в Java вы тоже можете написать библиотеку, которая вместо FileNotFound будет возвращать некий код (как в C), но так не делают, ибо так не принято.

                                                                                Да ладно!

                                                                                Вот, например: «boolean File.delete()», «boolean File.mkdir​()» и т.п.
                                                                                • 0

                                                                                  Ну ок, не знал. Много таких библиотек в общей массе?

                                                                                  • +2

                                                                                    Довольно много размазано по различным кускам стандартной библиотеки. Та же банальная работа с коллекциями часто имеет подобные методы для частых случаев (например, j.u.Map#get(key)). Инстанцирование exception'а достаточно дорогая операция из-за сбора стектрейса, если специально не выкидывать его сбор. И, соответственно, exception'ы, как правило, не используются для control flow.

                                                                • +1
                                                                  Не совсем. В Google в целом пришли к выводу, что польза от эксепшенов меньше, чем проблемы, которые они приносят.
                                                                  Ну вот зачем вы перевираете. Отказались исключительно в «C++».
                                                                  Гляньте на гитхабе в публичные гугловые исходники для Java… Посчитайте сколько там исключений… Инересно, почему от них не отказались?
                                                                  Или посмотрите на проекты на Python — тоже исключения повсеместно (в том числе кастомные).
                                                              • 0
                                                                Я не настаиваю, но думаю оверхед там не только из-за сохранения в стеке, но и само выполнение экепшеена требует больше ресурсов чем обработка одного if. В много-поточной системе, это всё выйдет с ещё с большей потерей ресурсов.
                                                                Ещё эта конструкция мне удобна тем, что если нужно обработать ошибку в зависимости от кода ошибки, то я это делаю сразу в нужном месте. И если нужно передать ошибку наверх то могу добавить что то к уже имеющемуся коду. Например какая именно функция выше уровнем не смогла открыть файл. Конечно же это можно сделать и с использованием эксепшена. Но это будет как раз замусоривание кода.
                                                                • –2

                                                                  Я не говорю, что вот "впилите экспешены, вот что бы прямо как в java", но почему прокидывание err наверх нельзя было сделать поведением по умолчанию, если другое не указано?


                                                                  Например, что бы можно было бы написать


                                                                  func t1(x int, y int) (int, error){
                                                                      r1 = t2(x,y) // неявная ошибка
                                                                      return r1;
                                                                  }

                                                                  вместо


                                                                  func t1(x int, y int) (int, error){
                                                                      r1, err = t2(x,y)
                                                                      if err != nil {
                                                                          return nil, err
                                                                      }
                                                                      return r1, nil;
                                                                  }
                                                                  • 0
                                                                    наверное так будет правильнее
                                                                    func t1(x int, y int) (r1 int, err, error){
                                                                        r1, err = t2(x,y)
                                                                        if err != nil {
                                                                            return
                                                                        }
                                                                        return 
                                                                    }
                                                                    

                                                                    Если у вас именованные переменные в возврате, то в return не обязательно их указывать.
                                                                    Я понимаю что пример упрощённый и в данном случае вообще можно if не делать.

                                                                    А если нужно сделать так?

                                                                    func t1(x int, y int) (r1 int, err, error){
                                                                        r1, err = t2(x,y)
                                                                        if err != nil {
                                                                            return errors.New("Имеенно это не могло вызвать t2 при причине:",err )
                                                                        }
                                                                        return 
                                                                    }
                                                                    }

                                                                    или так
                                                                    func t1(x int, y int) (err, error){
                                                                        r1, err = t2(x,y)
                                                                        if err != nil {
                                                                            r3, err = t3(x,y)
                                                                            if err != nil {
                                                                                return Err
                                                                            }
                                                                            //  Gthtl тем как вернуться на верх  сделать ещё несколько проверок и вызовов.
                                                                        }
                                                                        return 
                                                                    }
                                                                    }
                                                                    • –1
                                                                      > почему прокидывание err наверх нельзя было сделать поведением по умолчанию, если другое не указано

                                                                      То есть, если обработки нет и функция возвращает error, то прокидывать вставлять инструкции, которые будет прокидывать ошибку наверх. А если обработка есть, то, следовательно, поведение по умолчанию не нужно. Я думал над таким сценарием и мне он кажется в целом весьма нормальным. Возможно, я упустил какие-то возможные проблемы?
                                                              • +2

                                                                У такого решения есть два недостатка:


                                                                1. На каждую строку полезного целевого кода добавляется три с шаблонным кодом обработкой ошибок. Это сильно ухудшает читаемость и затрудняет сопровождение.
                                                                2. Компилятор ловит далеко не все случаи, когда обработка ошибок пропущена.
                                                                • 0

                                                                  Согласен, но за это вы получаете:


                                                                  1. Понятность (особенно другими людьми, читающими ваш код), что происходит в случае ошибки
                                                                  2. Отношение к error-path с таким же уважением, как и к happy-path коду (в отличие от эксепшенов)
                                                                  3. Простоту и понятность обработки ошибки в программе в целом — это простая переменная: получил ее, обработал. Никакой магии и талмудов, о том как правильно пользоваться, никакого "да эти 78% программистов просто не научились правильно пользоваться эксепшенами".
                                                                  • +3
                                                                    Понятность (особенно другими людьми, читающими ваш код), что происходит в случае ошибки

                                                                    Обычно происходит return nil, error что не добавляет ровно никакой полезной информации. Или ошибка вкладывается в _ и игнорируется — очень опасный вариант. Или ошибка не вкладывается в _ но все равно игнорируется — еще хуже.


                                                                    Отношение к error-path с таким же уважением, как и к happy-path коду (в отличие от эксепшенов)

                                                                    Целевой код решает поставленную задачу — без него вообще ничего не будет.
                                                                    Код в error-path минимизирует убытки — это очень важная отдельная ответственность, ее логично и реализовать отдельно, без смешения и копипасты.


                                                                    Простоту и понятность обработки ошибки в программе в целом — это простая переменная: получил ее, обработал.

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


                                                                    Отказ от более сложных и мощных средств никак не уменьшает сложность задачи.


                                                                    Как результат в Go есть механизм panic-recover-defer, делающий в точности то же самое, что и исключения. Следовательно, все равно придется решать, когда уместна паника, а когда код ошибки. Такие дела.

                                                                    • 0
                                                                      Обычно происходит return nil, error что не добавляет ровно никакой полезной информации.

                                                                      Обычно добавляется полезная информация и ошибка заворачивается в что-то вроде return nil, fmt.Errorf("decode: %s", err) или заворачивается в свой тип, реализующий интерфейс error — return nil, DecodeError{line: line, err: err}, но во многих ситуациях достаточно и просто передать ошибку наверх — это нормально. Суть здесь в том, что ваш коворкер или вы через 3 месяца, читая этот код, мгновенно будете видеть, что происходит при возникновении ошибки, уменьшая таким образом количество догадок, ошибок в понимании workflow программы и подкапотной магии в целом.


                                                                      Код в error-path минимизирует убытки — это очень важная отдельная ответственность, ее логично и реализовать отдельно

                                                                      Ну это подход тех, кто привык к эксепшенам. Авторы Go же считают, что error path код, не нужно "реализовывать отдельно", и стимулируют к этому относиться как такому же важному коду, как и happy path. Написал if, напиши и else, другими словами. Вы можете быть с этим не согласны, но это тот подход, который выбран в Go и который, на самом деле, миллионы программистов считают более правильным и удобным.


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

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


                                                                      Отказ от более сложных и мощных средств никак не уменьшает сложность задачи.

                                                                      А оно и не должно. Сложность задачи (essential complexity) средствами не уменьшается, а вот выбор средств с меньшей сложностью (accidental complexity) это как раз то, к чему вся софтверно инжинерная индустрия и стремится (ну, не везде, правда))).


                                                                      Следовательно, все равно придется решать, когда уместна паника, а когда код ошибки.
                                                                      Именно, и паника очень редко когда на нужна по факту. И, к слову, вы написали "код ошибки", но коды ошибки это в С. В Go error не код, это интерфейсный тип, и это, мягко говоря, несравнимо.
                                                                      • 0
                                                                        Обычно добавляется полезная информация и ошибка заворачивается в что-то вроде return nil, fmt.Errorf("decode: %s", err) или заворачивается в свой тип, реализующий интерфейс error — return nil, DecodeError{line: line, err: err},

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


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

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


                                                                        вторы Go же считают, что error path код, не нужно "реализовывать отдельно", и стимулируют к этому относиться как такому же важному коду, как и happy path.

                                                                        Сможете показать, где это стимулируется средствами языка, а не просто руководством по стилю?
                                                                        Error path НЕ такой же важный код как happy path по определению.
                                                                        Без happy path у вас вообще ничего нет, без error path вы можете нести бОльшие убытки при нештатных ситуациях.
                                                                        При использовании кодов ошибок их обработка перемешана с бархатным путем похлеще чем спагетти, занимает больше места (три строчки на одну), содержит массу копипасты, требует читать весь код при анализе ошибочной ситуации.


                                                                        Сложность задачи (essential complexity) средствами не уменьшается, а вот выбор средств с меньшей сложностью (accidental complexity) это как раз то, к чему вся софтверно инжинерная индустрия и стремится (ну, не везде, правда))).

                                                                        Задача обработки ошибок — это accidental complexity, никакой сущностной сложности в ней нет.
                                                                        А вот happy path — это как раз essential complexity.
                                                                        Исключения позволяют обработать ошибки концентрированно, централизовано, без копипасты, с максимально читаемым целевым кодом.


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

                                                                        Да неужели? Если у вас случилась нештатная ситуация и она не совсем верно обрабатывается с помощью кодов ошибок, то вам придется


                                                                        1. Узнать о проблеме (необработанные коды ошибок молчат как партизаны)
                                                                        2. Предположить, где она возникла
                                                                        3. Пройти по всему стеку, проверив, как ее отрабатывает каждый метод в цепочке вызовов.
                                                                        4. Если предположение оказалось неверным вернуться к пункту 2

                                                                        С исключениями:


                                                                        1. У вас будет стек с указанием места, где конкретно возникла ошибка.
                                                                        2. Проверять нужно только места перехвата исключений (а не всю цепочку вызовов)

                                                                        миллионы программистов считают более правильным и удобным.

                                                                        Миллионы леммингов не могут ошибаться. У человека чисто биологически есть масса систематических ошибок мышления, поэтому отсылка к миллионам сторонников релевантна только при голосовании.


                                                                        Именно, и паника очень редко когда нужна по факту.

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


                                                                        И, к слову, вы написали "код ошибки", но коды ошибки это в С. В Go error не код, это интерфейсный тип, и это, мягко говоря, несравнимо.

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

                                                                        • 0
                                                                          Полный эквивалент перехвата исключений на границе абстракций. Понимания требуется столько же.

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


                                                                          Error path НЕ такой же важный код как happy path по определению.

                                                                          Это вы в это верите, и, почему-то считаете это какой-то абсолютной истиной. В Go это убеждения очень не приветствуется и язык вас заставит начать относиться к error-path как к такому же важному коду и сделает это новым определением.


                                                                          требует читать весь код при анализе ошибочной ситуации.

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


                                                                          Исключения позволяют обработать ошибки концентрированно, централизовано

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


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

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


                                                                          Кстати, а когда нужна паника по вашему мнению?

                                                                          Когда ошибка критична и программа (или модуль программы) не могут дальше продолжать из-за этой ошибки и должна прекратить выполнение no matter what.


                                                                          "Код ошибки" — это роль, а не конкретный тип вроде целого числа.

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

                                                                          • +2
                                                                            Ни разу не полный. При явном возврате, вы тут же видите что происходит в error path. В случае исключений вам нужно скроллить вниз функции, держа в голове типы исключений.

                                                                            Не вниз функции, а до ближайшей секции except.
                                                                            Типы исключений в голове нужно держать ровно в той же степени, как и конкретный тип, реализующий интерфейс error. Если вам не нужен второй — то и первый не нужен точно так же.
                                                                            Коды ошибок требует обработать ошибку сразу, исключения позволяет это сделать в специально отведенном месте.
                                                                            Единственный плюс за коды ошибок — легче увидеть необработанное при ревью кода.


                                                                            Это вы в это верите, и, почему-то считаете это какой-то абсолютной истиной. В Go это убеждения очень не приветствуется и язык вас заставит начать относиться к error-path как к такому же важному коду и сделает это новым определением.

                                                                            Вы только что сами утверждали, что язык ничего не заставляет. В нем же есть "исключения здорового человека" AKA panic.
                                                                            Давайте уж определимся, кто именно заставляет — язык или руководство по стилю?


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

                                                                            Не телепат и могу понять лишь то что написано. С исключениями для понимания читать придется меньше.


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

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


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

                                                                            Может, но как и в любом варианте с кодами ошибок, такая информация должна добавляться вручную. Исключения дают все это из коробки автоматически.


                                                                            Когда ошибка критична и программа (или модуль программы) не могут дальше продолжать из-за этой ошибки и должна прекратить выполнение no matter what.

                                                                            И зачем тогда нужен recover, если no matter what?


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

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


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

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

                                                                            • –4
                                                                              Не вниз функции, а до ближайшей секции except.

                                                                              А где обычно "ближайшая секция except"? Никогда не видел вверху функции или сразу под вызовом. Давайте по сути.


                                                                              Единственный плюс за коды ошибок — легче увидеть необработанное при ревью кода.

                                                                              А вы специально продолжаете называть возврат ошибок в Go "кодами ошибок"?


                                                                              Давайте уж определимся,

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


                                                                              С исключениями для понимания читать придется меньше.

                                                                              И понимать меньше, да.


                                                                              Исключения дают все это из коробки автоматически.

                                                                              И это ещё одна глупость — стектрейс далеко не во всех ошибках нужен. Но у вас же нет других способов, поэтому вы тратите память и такты процессора, чтобы гонять стекйтрейсы по поводу и без повода, даже не отдавая в этом отчет. Это не только лишний минус к производительности, но и просто неправильно. Почти каждая Python программа, например, вместо понятного сообщения для в консоль вроде "Ctrl-C pressed, aborting" или "File not found" вываливает стектрейс, но очень многие привыкшие к этому даже не понимают, почему это абсурдно. В Go вы получаете стектрейс только когда это надо.


                                                                              И зачем тогда нужен recover, если no matter what?

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


                                                                              С точки зрения пользователя — его код это как отдельная программа, с точки зрения вашей библиотеки — его код это отдельная функция — черный ящик. В таком случае имеет смысл на всякий случай поставить recover и красиво обработать панику, если вдруг что.


                                                                              Типичный пример — net/http библиотека и HandlerFunc.


                                                                              Структурно рекомендуемый паттерн обработки ошибок в Go — это коды ошибок

                                                                              Вы же троллите, да? Коды ошибок — это устоявшийся термин из С и С++, где возвращаются действительно коды ошибок, и далее по ним делается switch или подобные проверки, что в купе с единственным значением возврата, делает механизм возвратов кодов ошибок очень неудобным. Go этих недостатков лишен и интерфейсный тип ошибки даёт гибкость несравнимую с "кодами ошибок". Но вы продолжаете всё равно называть это на свой лад, только заводя дискуссию в тупик.

                                                                              • +1
                                                                                А вы специально продолжаете называть возврат ошибок в Go "кодами ошибок"?

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


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

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


                                                                                И понимать меньше, да.

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


                                                                                И это ещё одна глупость — стектрейс далеко не во всех ошибках нужен.

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


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

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

                                                                                • –4
                                                                                  И это ещё одна глупость — стектрейс далеко не во всех ошибках нужен.
                                                                                  Вы снова хамите. Зачем?

                                                                                  Вам кажется хамством утверждение, что не во всех ошибках нужен стектрейс? Я думал я уже ничему тут не удивляюсь :)


                                                                                  И попробуйте дать ответ на прямо поставленный вопрос.

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


                                                                                  Вы так и не дали подходящего общего термина

                                                                                  Дал, несмотря на то, что вы сами и не попытались взять. Хотите писать простыни комментариев про то как вас никто не заставит назвать вещи своими именами — пишите на здоровье. Мне это больше не интересно.

                                                                                  • +1
                                                                                    Простите, я вот тоже не понял, какое же вы предлагаете использовать название вместо «коды ошибки», которое наверное не совсем верное в том смысле, что кодами обычно называют какие-то числа или возможно перечисления, а не целые структуры, но подход-то возвращения ошибки из метода тот же самый? Напишите, пожалуйста, как в го-мире принято называть такой способ обработки ошибок ответом на этот комментарий, чтобы все кто тоже не понял, смог бы посмотреть сюда и удовлетворить своё недопонимание.
                                                                                    • –2

                                                                                      Просто "возврат ошибки", никаких кодов.

                                                                      • +1
                                                                        Обычно добавляется полезная информация и ошибка заворачивается в что-то вроде return nil, fmt.Errorf(«decode: %s», err) или заворачивается в свой тип, реализующий интерфейс error — return nil, DecodeError{line: line, err: err}

                                                                        Очевидно, что полезность «return nil, fmt.Errorf('decode: %s', err)» стремится к нулю, т.к. эта ошибка для пользователя (причем, без учета i18n), а не программы, ее нельзя категоризировать и далее каким-либо осмысленным образом обработать.

                                                                        А возвращение в стиле «return nil, DecodeError{line: line, err: err}», по-моему, упрется в то же, что и упираются исключения — лень программиста завести «DecodeError» и написать правильно.
                                                                        • –4

                                                                          Мило. Вы это Go программистам пытаетесь доказать, что в Go обработка ошибок стремиться к нулю, или тем, кто Go не знает? :)

                                                                          • +1

                                                                            Не передергивайте, речь шла про конструкцию return nil, fmt.Errorf('decode: %s', err) а не про обработку ошибок в общем.

                                                                            • –2

                                                                              Почему вы отвечаете за другого человека и объясняете мне, что вы считаете, что он имел ввиду? Куда вы дели из его ответа конструкцию return nil, DecodeError{line: line, err: err} и фантазии автора о том, во что оно упрётся?
                                                                              Или вы тут один человек под разными аккаунтами?

                                                                              • +1
                                                                                Потому что мне есть что написать, потому и пишу. Кажется, правилами хабра это не запрещено.

                                                                                Что же до строчки `return nil, DecodeError{line: line, err: err}` — то при чем тут она? Про полезность стремящуюся к нулю говорилось в контексте первой строчки, а не этой. Второй вариант как раз нормальный.
                                                                                • –2

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

                                                                                  • 0
                                                                                    Я сейчас ничего доказать не пытаюсь. Я заметил что в споре был применен некорректный аргумент.
                                                                          • +2
                                                                            Мило. Вы это Go программистам пытаетесь доказать

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

                                                                            Кроме этого, упомянутая проблема «стремления пользы к нулю» справедлива не только для Go, а вообще для любой системы, в которой будет использоваться подобная конструкция (строка ошибка). В C++ это будет:

                                                                            throw «some error useless description»;.
                                                                            • 0
                                                                              Приведу еще ссылку на обсуждение по теме:
                                                                              https://stackoverflow.com/questions/6248404/c-exceptions-is-throwing-c-string-as-an-exception-bad
                                                                              • –2
                                                                                упомянутая проблема «стремления пользы к нулю»

                                                                                Я всё же позволю не согласиться с этим — во многих случаях как раз важно дать пользователю четкое описание того, что произошло, и строковое описание ошибки, дополненное на каждому уровне стека оказывается именно тем, что нужно. Напирмер, если пользователь запускает программу, и получает в ответ строку Can't load config: open ~/.config/myapp: insufficient permissions — это почти образец того, как подобная ошибка и должна быть обработана и подана юзеру. Тут не нужны стектрейсы. не нужна метаинформация — простая строка, объясняющая чуть возникшей ситуации, которая трактуется программой, как проблема.


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

                                                                                • 0

                                                                                  Сообщения об ошибках, также как и любые сообщения, нужно отображать локализованными. Вот только такие простые конструкции как приведенная вами не позволяют локализовать сообщение об ошибке.

                                                                                  • –1
                                                                                    Сообщения об ошибках, также как и любые сообщения, нужно отображать локализованными.

                                                                                    Не обязательно.


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

                                                                                    Элементарно позволяют.

                                                                                    • 0
                                                                                      И как же предполагается делать локализацию сообщения «Can't load config: open ~/.config/myapp: insufficient permissions»?
                                                                                      • 0

                                                                                        return nil, fmt.Errorf("%s: %s", i18n("decode"), err)
                                                                                        return nil, DecodeError{line: line, err: i18n(err)}


                                                                                        А откуда такая абсолютная убежденность, что все ошибки необходимо локализовать? Спрашиваю чисто из практического опыта — в серверах, например, часто единственный пользователь, который будет читать ошибки, это технический персонал (разработчики, девопс, и тд). и проблем с пониманием английского нет.

                                                                                        • +1

                                                                                          Вот после таких решений (я о первом) и появляются "локализованные" сообщения вида "Ошибка декодировать: открыть файл: нехватка разрешений".

                                                                                          • –1
                                                                                            Ещё раз, о чём вы спорите?
                                                                                          • 0
                                                                                            return nil, fmt.Errorf("%s: %s", i18n(«decode»), err)

                                                                                            Ха-ха-ха. Встречал я подобный код, только вместо i18n был стразу MessageBox. Чего мелочится-то? :-)

                                                                                            В 99% случаях это нарушение роли компонента в системе.
                                                                                            • –1
                                                                                              О чём вы сейчас спорите?
                                                                                              • +2
                                                                                                О чём вы сейчас спорите?

                                                                                                О пользе типизированных ошибок, которые часто ленятся использовать программисты с качестве возвращаемого результата и в качестве объекта исключения.
                                                                                                • –1
                                                                                                  О пользе типизированных ошибок

                                                                                                  Ясно. А кто-то говорил, что они не полезны?

                                                                                                  • +2

                                                                                                    Да, это вы говорили:


                                                                                                    Я всё же позволю не согласиться с этим — во многих случаях как раз важно дать пользователю четкое описание того, что произошло, и строковое описание ошибки, дополненное на каждому уровне стека оказывается именно тем, что нужно. Напирмер, если пользователь запускает программу, и получает в ответ строку Can't load config: open ~/.config/myapp: insufficient permissions — это почти образец того, как подобная ошибка и должна быть обработана и подана юзеру. Тут не нужны стектрейсы. не нужна метаинформация — простая строка, объясняющая чуть возникшей ситуации, которая трактуется программой, как проблема.
                                                                                                    • –1
                                                                                                      Да, это вы говорили:

                                                                                                      В каком месте из приведенной цитаты следует, что "типизированные ошибки бесполезны"?

                                                                                                      • 0

                                                                                                        С первых же слов — по контексту беседы, вы не соглашаетесь с необходимостью типизированных ошибок.

                                                                                                        • –1
                                                                                                          Я не соглашаюсь с тем, что строковые представления ошибок не имеют ценности. Пусть А = строковые ошибки, Б = типизированные ошибки. Диалог:

                                                                                                          > ценность А стремится к нулю
                                                                                                          я> не согласен, есть много случаев когда А имеет смысл
                                                                                                          > значит вы утверждаете, что Б бесполезно

                                                                                                          Извините, но я не вижу как можно продолжать дискуссию с такими нарушениями базовой логики.
                                                                                                          • 0

                                                                                                            В таком случае логика нарушена у вас, вот в этом комментарии:


                                                                                                            Ясно. А кто-то говорил, что они не полезны?

                                                                                                            Потому что получается вот так:


                                                                                                            Вы> A полезно
                                                                                                            f> A бесполезно, нужно использовать B
                                                                                                            Вы> разве я говорил что B бесполезно?

                                                                        • 0
                                                                          простите, я тут немного влезу. Просто когда я читаю такую аргументацию, я это слышу примерно так: да, мы сделали неудобно для использования, зато любой идиот это поймёт. Значит вторых использующих язык предполагается даже больше чем тех кому важно удобство и кто в состоянии воспользоваться эксепшенами так, чтобы ничего себе не отстрелить. Тут вот как раз я и понимаю, что это не мой язык, я ничего против него не имею, пользуйтесь на здоровье если нравится и решает задачи, но я воздержусь, спасибо.
                                                                          • 0
                                                                            кому важно удобство и кто в состоянии воспользоваться эксепшенами

                                                                            Я слушаю эти сказки про "удобство" и "в состоянии выучить" эксепшенов уже лет 10. Практика показывает, что подавляющее большинство кода на эксепшенах написано через одно место и создает много проблем. Последний раз, когда я спорил о пользе эксепшенов и слушал о том, что "это программисты были идиоты", спор закончился тем, что мне пришлось переводить сервис этого человека в докер-контейнер, и там было как раз важно ловить ошибки, что не так (порт не открыт например, или файл не найден или еще что) — и ни одна, ни одна из действительно ошибочных ситуаций не была корректно обработана. Эксепшены стимулировали "выбросил и словил наверху", такой подход в целом заставляет считать ошибки чем-то не особо важным, чем-то "а, потом займусь", и результат был на лицо. Спасло только использование strace. Спрашивается — зачем был вообще этот механизм ошибок "не для идиотов, а для элитных программистов, смотрящих свысока", который "очень удобный для использования", если всё равно толку от него ноль? Можно было просто делить на ноль и падать — было бы эффективнее. И я такого уже насмотрелся достаточно.
                                                                            Более того, было тут исследование статическим анализом 400000 репозитороев на Java, в котором оказалось, что 78% проектов просто выбрасывают GeneralException и ловят его в самом верху. Ладно, вы можете не верить моему опыту и опыту сотен других, но с цифрами и статистикой сложно спорить. Поэтому лично я рад, что хотя бы в одном языке к вопросу подошли к практической и эмпирической точки зрения, а не с теоретических фантазий.


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