Обработка ошибок в Go 2

    title


    Буквально пару дней назад в Денвере закончилась очередная, уже 5-я по счёту, крупнейшая конференция по Go – GopherCon. На ней команда Go сделала важное заявление – черновики предварительного дизайна новой обработки ошибок и дженериков в Go 2 опубликованы, и все приглашаются к обсуждению.


    Я постараюсь подробно пересказать суть этих черновиков в трёх статьях.


    Как многим, наверняка, известно, в прошлом году (также на GopherCon) команда Go объявила, что собирает отчёты (experience reports) и предложения для решения главных проблем Go – тех моментов, которые по опросам собирали больше всего критики. В течении года все предложения и репорты изучались и рассматривались, и помогли в создании черновиков дизайна, о которых и будет идти речь.


    Итак, начнём с черновиков нового механизма обработки ошибок.


    Для начала, небольшое отступление:


    1. Go 2 это условное название – все нововведения будут частью обычного процесса выпуска версий Go. Так что пока неизвестно, будет ли это Go 1.34 или Go2. Сценария Python 2/3 не будет железно.
    2. Черновики дизайна это даже не предложения (proposals), с которых начинается любое изменение в библиотеке, тулинге или языке Go. Это начальная точка для обсуждения дизайна, предложенная командой Go после нескольких лет работы над данными вопросами. Всё, что описано в черновиках с большой долей вероятности будет изменено, и, при наилучших раскладах, воплотится в реальность только через несколько релизов (я даю ~2 года).

    В чём проблема с обработкой ошибок в Go?


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


    Возьмём пример гипотетического Go с исключениями:


    func CopyFile(src, dst string) throws error {
        r := os.Open(src)
        defer r.Close()
    
        w := os.Create(dst)
        io.Copy(w, r)
        w.Close()
    }

    Это приятный, чистый и элегантный код. Он также некорректый: если io.Copy или w.Close завершатся неудачей, данный код не удалит созданный и недозаписанный файл.


    С другой стороны, код на реальном Go выглядит так:


    func CopyFile(src, dst string) error {
        r, err := os.Open(src)
        if err != nil {
            return err
        }
        defer r.Close()
    
        w, err := os.Create(dst)
        if err != nil {
            return err
        }
        defer w.Close()
    
        if _, err := io.Copy(w, r); err != nil {
            return err
        }
        if err := w.Close(); err != nil {
            return err
        }
    }

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


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


    Проще говоря, в Go слишком много проверки ошибок и недостаточно обработки ошибок. Более полноценная версия кода выше будет выглядеть вот так:


    func CopyFile(src, dst string) error {
        r, err := os.Open(src)
        if err != nil {
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
        }
        defer r.Close()
    
        w, err := os.Create(dst)
        if err != nil {
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
        }
    
        if _, err := io.Copy(w, r); err != nil {
            w.Close()
            os.Remove(dst)
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
        }
    
        if err := w.Close(); err != nil {
            os.Remove(dst)
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
        }
    }

    Исправление проблем сделало код корректным, но никак не чище или элегантней.


    Цели


    Команда Go ставит перед собой следующие цели для улучшения обработки ошибок в Go 2:


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

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


    Дизайн


    Предложенный дизайн вводит две новых синтаксические формы.


    • check(x,y,z) или check err обозначающую явную проверку ошибки
    • handle – определяющую код, обрабатывающий ошибки

    Если check возвращает ошибку, то контроль передаётся в ближайший блок handle (который передаёт контроль в следущий по лексическому контексту handler, если такой есть, и. затем, вызывает return)


    Код выше будет выглядеть так:


    func CopyFile(src, dst string) error {
        handle err {
            return fmt.Errorf("copy %s %s: %v", src, dst, err)
        }
    
        r := check os.Open(src)
        defer r.Close()
    
        w := check os.Create(dst)
        handle err {
            w.Close()
            os.Remove(dst) // (только если check упадёт)
        }
    
        check io.Copy(w, r)
        check w.Close()
        return nil
    }

    Этот синтаксис разрешён также в функциях, которые не возвращают ошибки (например main). Следующая программа:


    func main() {
        hex, err := ioutil.ReadAll(os.Stdin)
        if err != nil {
            log.Fatal(err)
        }
    
        data, err := parseHexdump(string(hex))
        if err != nil {
            log.Fatal(err)
        }
    
        os.Stdout.Write(data)
    }

    может быть переписана как:


    func main() {
        handle err {
            log.Fatal(err)
        }
    
        hex := check ioutil.ReadAll(os.Stdin)
        data := check parseHexdump(string(hex))
        os.Stdout.Write(data)
    }

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


    func printSum(a, b string) error {
        x, err := strconv.Atoi(a)
        if err != nil {
            return err
        }
        y, err := strconv.Atoi(b)
        if err != nil {
            return err
        }
        fmt.Println("result:", x + y)
        return nil
    }

    может быть переписан как:


    func printSum(a, b string) error {
        handle err { return err }
        x := check strconv.Atoi(a)
        y := check strconv.Atoi(b)
        fmt.Println("result:", x + y)
        return nil
    }

    или даже вот так:


    func printSum(a, b string) error {
        handle err { return err }
        fmt.Println("result:", check strconv.Atoi(x) + check strconv.Atoi(y))
        return nil
    }

    Давайте рассмотрим подробнее детали предложенных конструкций check и handle.


    Check


    check это (скорее всего) ключевое слово, которое чётко выражает действие "проверка" и применяется либо к переменной типа error, либо к функции, возвращающую ошибку последним значением. Если ошибка не равна nil, то check вызывает ближайший обработчик(handler), и вызывает return с результатом обработчика.


    Следующий пример:


    v1, ..., vN := check <выражение>

    равнозначен этому коду:


    v1, ..., vN, vErr := <выражение>
    if vErr != nil {
        <error result> = handlerChain(vn)
        return
    }

    где vErr должен иметь тип error и <error result> означает ошибку, возвращённую из обработчика.


    Аналогично,


    foo(check <выражение>)

    равнозначно:


    v1, ..., vN, vErr := <выражение>
    if vErr != nil {
        <error result> = handlerChain(vn)
        return
    }
    foo(v1, ..., vN)

    Check против try


    Изначально пробовали слово try вместо check – оно более популярное/знакомое, и, например, Rust и Swift используют try (хотя Rust уходит в пользу постфикса ? уже).


    try неплохо читался с функциями:


    data := try parseHexdump(string(hex))

    но совершенно не читался со значениями ошибок:


    data, err := parseHexdump(string(hex))
    if err == ErrBadHex {
        ... special handling ...
    }
    try err

    Кроме того, try всё таки несёт багаж cхожести с механизмом исключений и может вводить в заблуждение. Поскольку предложенный дизайн check/handle существенно отличается от исключений, выбор явного и красноречивого слова check кажется оптимальным.


    Handle


    handle описывает блок, называемый "обработчик" (handler), который будет обрабатывать ошибку, переданную в check. Возврат (return) из этого блока означает незамедлительный выход из функции с текущими значениями возвращаемых переменных. Возврат без переменных (то есть, просто return) возможен только в функциях с именованными переменными возврата (например func foo() (bar int, err error)).


    Поскольку обработчиков может быть несколько, формально вводится понятие "цепочки обработчиков" – каждый из них это, по сути, функция, которая принимает на вход переменную типа error и возвращает те же самые переменные, что и функция, для которой обработчик определяется. Но семантика обработчика может быть описана вот так:


    func handler(err error) error {...}

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


    Порядок обработчиков


    Важный момент для понимания – в каком порядке будут вызываться обработчики, если их несколько. Каждая проверка (check) может иметь разные обработчики, в зависимости от скопа, в котором они вызываются. Первым будет вызван обработчик, который ближе всего объявлен в текущем скопе, вторым – следующий в обратном порядке объявления. Вот пример для лучшего понимания:


    func process(user string, files chan string) (n int, err error) {
        handle err { return 0, fmt.Errorf("process: %v", err)  }      // handler A
        for i := 0; i < 3; i++ {
            handle err { err = fmt.Errorf("attempt %d: %v", i, err) } // handler B
            handle err { err = moreWrapping(err) }                    // handler C
    
            check do(something())  // check 1: handler chain C, B, A
        }
        check do(somethingElse())  // check 2: handler chain A
    }

    Проверка check 1 вызовет обработчики C, B и A – именно в таком порядке. Проверка check 2 вызовет только A, так как C и B были определены только для скопа for-цикла.


    Конечно, в данном дизайне сохраняется изначальный подход к ошибкам как к обычным значениям. Вы всё также вольны использовать обычный if для проверки ошибки, а в обработчике ошибок (handle) можно (и нужно) делать то, что наилучшим образом подходит ситуации – например, дополнять ошибку деталями перед тем, как обработать в другом обработчике:


    type Error struct {
        Func string
        User string
        Path string
        Err  error
    }
    
    func (e *Error) Error() string
    
    func ProcessFiles(user string, files chan string) error {
        e := Error{ Func: "ProcessFile", User: user}
        handle err { e.Err = err; return &e } // handler A
        u := check OpenUserInfo(user)         // check 1
        defer u.Close()
        for file := range files {
            handle err { e.Path = file }       // handler B
            check process(check os.Open(file)) // check 2
        }
        ...
    }

    Стоит отметить, что handle несколько напоминает defer, и можно решить, что порядок вызова будет аналогичным, но это не так. Эта разница – одна из слабых место данного дизайна, кстати. Кроме того, handler B будет исполнен только раз – аналогичный вызов defer в том же месте, привёл бы ко множественным вызовам. Go команда пыталась найти способ унифицировать defer/panic и handle/check механизмы, но не нашла разумного варианта, который бы не делал язык обратно-несовместимым.


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


    Паника (panic) в обработчиках исполняется так же, как и в теле функции.


    Обработчик по-умолчанию


    Ещё одна ошибка компиляции – если код обработчика пуст (handle err {}). Вместо этого вводится понятие "обработчика по-умолчанию" (default handler). Если не определять никакой handle блок, то, по-умолчанию, будет возвращаться та же самая ошибка, которую получил check и остальные переменные без изменений (в именованных возвратных значениях; в неименованных будут возвращаться нулевые значения — zero values).


    Пример кода с обработчиком по-умолчанию:


    func printSum(a, b string) error {
        x := check strconv.Atoi(a)
        y := check strconv.Atoi(b)
        fmt.Println("result:", x + y)
        return nil
    }

    Сохранение стека вызова


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


    func TestFoo(t *testing.T) {
        handle err {
            t.Helper()
            t.Fatal(err)
        }
        for _, tc := range testCases {
            x := check Foo(tc.a)
            y := check Foo(tc.b)
            if x != y {
                t.Errorf("Foo(%v) != Foo(%v)", tc.a, tc.b)
            }
        }
    }

    Затенение (shadowing) переменных


    Использование check может практически убрать надобность в переопределении переменных в краткой форме присваивания (:=), поскольку это было продиктовано именно необходимостью переиспользовать err. С новым механизмом handle/check затенение переменных может вообще стать неактуальным.


    Открытые вопросы


    defer/panic


    Использование похожих концепций (defer/panic и handle/check) увеличивает когнитивную нагрузку на программиста и сложность языка. Не очень очевидные различия между ними открывают двери для нового класса ошибок и неправильного использования обоих механизмов.


    Поскольку handle всегда вызывается раньше defer (и, напомню, паника в коде обработчика обрабатывается так же, как и в обычном теле функции), то нет способа использовать handle/check в теле defer-а. Вот этот код не скомпилируется:


    func Greet(w io.WriteCloser) error {
        defer func() {
            check w.Close()
        }()
        fmt.Fprintf(w, "hello, world\n")
        return nil
    }

    Пока не ясно, как можно красиво решить эту ситуацию.


    Уменьшение локальности кода


    Одним из главных преимуществ нынешнего механизма обработки ошибок в Go является высокая локальность – код обработчика ошибки находится очень близко к коду получения ошибки, и исполняется в том же контексте. Новый же механизм вводит контекстно-зависимый "прыжок", похожий одновременно на исключения, на defer, на break и на goto. И хотя данный подход сильно отличается от исключений, и больше похож на goto, это всё ещё одна концепция, которую программисты должны будут учить и держать в голове.


    Имена ключевых слов


    Рассматривалось использование таких слов как try, catch, ? и других, потенциально более знакомых из других языков. После экспериментирования со всеми, авторы Go считают, что check и handle лучше всего вписываются в концепцию и уменьшают вероятность неверного трактования.


    Что делать с кодом, в котором имена handle и catch уже определены, пока тоже не ясно (не факт, что это будут ключевые слова (keywords) ещё).


    Часто задаваемые вопросы


    Когда выйдет Go2?


    Неизвестно. Учитывая прошлый опыт нововведений в Go, от стадии обсуждения до первого экспериментального использования проходит 2-3 релиза, а официальное введение – ещё через релиз. Если отталкиваться от этого, то это 2-3 года при наилучших раскладах.


    Плюс, не факт, что это будет Go2 – это вопрос брендинга. Скорее всего, будет обычный релиз очередной версии Go – Go 1.20 например. Никто не знает.


    Разве это не то же самое, что исключения?


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


    Не разделит ли это Go программистов на 2 лагеря – тех, кто останется верным if err != nil {} проверкам, и сторонников handle/check?


    Неизвестно, но расчёт на то, что if err будет мало смысла использовать, кроме специальных случаев – новый дизайн уменьшает количество символов для набора, и сохраняет явность проверки и обработки ошибок. Но, время покажет.


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


    Является. Расчёт на то, что выгода от этого усложнения перевесит минусы самого факта усложнения.


    Это окончательный дизайн и точно ли он будет принят?


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


    Я знаю, как сделать дизайн лучше! Что мне делать?


    Напишите статью с объяснением вашего видения и добавьте её в вики-страничку Go2ErrorHandlingFeedback


    Резюме


    • Предложен новый механизм обработки ошибок в будущих версиях Go —  handle/check
    • Обратно-совместим с нынешним
    • Проверка и обработка ошибок остаются явными
    • Сокращается количество текста, особенно в кусках кода, где много повторений однотипных ошибок
    • В грамматику языка добавляются два новых элемента
    • Есть открытые/нерешённые вопросы (взаимодействие с defer/panic)

    Ссылки



    Мысли? Комментарии?


    Share post

    Comments 296

      +6
      Вся эта семантика явно делает го сложнее для чтения и написания, но решение давно просилось, и в принципе выглядит не так уж плохо (но и не сказать, чтобы прямо супер очевидно) :). Что кто думает?
        +7
        handle err {
                w.Close()
        }
        
        check w.Close()

        Ммм, это пять :-)


        func printSum(a, b string) error {
            x := check strconv.Atoi(a)
            y := check strconv.Atoi(b)
            check fmt.Println("result:", x + y)
            return nil
        }

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

          +1
          Так как подавляющее большинство функций может завершиться ошибкой, то получается, что перед всеми вызовами будут писать check. Какой смысл в такой "явности" ума не приложу. Тем более что всё равно не понятно какие именно ошибки может кинуть функция и все ли из них были обработаны.

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

            +2
            Ну суть как раз в явности — видно какая функция возвращает ошибку.

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


            Все явно — где и как ошибка обработана.

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

              –4
              Да все функции возвращают ошибку.

              Это неверное утверждение.
              Быстрый поиск по стандартной библиотеке:
              $ grep -r '^func' . | grep error | wc -l
              12928
              $ grep -r '^func' . | grep -v error | wc -l
              38878


              Куда важнее где и какая ошибка не обработана и на этот вопрос Go не отвечает.

              Статический анализ не может дать ответ во всех возможных случаях, нужно ли проверять ошибку или нет. Например, `fmt.Println()` возвращает ошибку, но в большинстве случаев практического смысла проверять её нет. Даже линтер `errcheck` тут не будет ругаться.
                0
                $ grep -r '^func'. | grep error | wc -l
                12928
                $ grep -r '^func'. | grep -v error | wc -l
                38878

                Это неверный подход к анализу. Из выборки также необходимо исключить те функции, которые ничего не возвращают (процедуры, которые не задеклалированы в языке). А почти треть всех функций с error все же значимая часть кода, несмотря на пример с `fmt.Println()`, который больше исключение подтверждающий правило.

                В целом направление интересное и возможно верное, хотя check станет самым частым словом в теле функции как в примере выше. Хоть и укорачивает, но слегка нечитабельно.
                Возможно, как вариант вообще избавиться от слова check, введя дополнительный вид присваивания? Например, так:
                func printSum(a, b string) error {
                    x ~ strconv.Atoi(a)
                    y ~ strconv.Atoi(b)
                    check fmt.Println("result:", x + y)
                    return nil
                }

                Где `~` есть эквивалент `:= check`. Или вот так, получше вариант:
                func printSum(a, b string) error {
                    @x := strconv.Atoi(a)
                    @y := strconv.Atoi(b)
                    check fmt.Println("result:", x + y)
                    return nil
                }
                  0

                  Последний пример напомнил перл с его:


                  @file = open($file) or die "cant open file $file: $!"
                    0
                    Ну это не анализ был, а наглядное опровержение фразы «все функции возвращают ошибку».

                    Насчёт односимвольных синтаксических конструкций – в Go они никогда не приживались, и, надеюсь, и не будут. `check` несёт смысл в самом названии и, даже без чтения спецификации/книжек можно догадаться о его функции, а вот `~` и `@` уже никак не догадаешься сходу.
                      0

                      @ и ошибки это из php, там правда смысл несколько иной: http://php.net/manual/ru/language.operators.errorcontrol.php

                      +2

                      Ой как весело комментировать только половину фразы.


                      А как вы понимаете надо ли обрабатывать ошибку от fmt.Println()? Мне вот ни из сигнатуры, ни из документации это не понятно:


                      func Println(a ...interface{}) (n int, err error)
                      Println formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.

                      Что за ошибки? В каких случаях возникают? Насколько критичные?


                      fmt.Println("result:", x + y)

                      Функция не возвращает ошибок? Или возвращает, но мы их игнорируем? Или мы забыли обработать ошибки? Или мы не знали, что функция вообще возвращает ошибки? Или знали лишь о 3 из 5 вариантах падения и не были в курсе, что оставшиеся 2 надо обработать по особому?

                        –4
                        А как вы понимаете надо ли обрабатывать ошибку от fmt.Println()? Мне вот ни из сигнатуры, ни из документации это не понятно.


                        В комментарии сказано «write error». Также в нём сказано, что запись производится в stdout. Этого достаточно, чтобы сообразить, что возможна ошибка записи в stdout и уже вам судить, насколько это вероятная ситуация и что в ней делать.

                        А про «половину фразы» не надо – ради краткости есть смысл не копировать все предложения, которые не меняют смысл вашего утверждения про «все функции возвращают ошибку».
                          0

                          И какая же «ошибка записи» возможна? man 3p write, раздел ERRORS описывает 23 возможных ошибки, хотя часть с одними кодами, часть применима только к write() или только к pwrite() (кстати, ещё могли сообразить обёртку над writev(), в определённых случаях функция более удобная, тем более если нужно писать более одной строки), и всё применимо только к linux. Какие из этих ошибок может вернуть fmt.Println, а какие либо не возникнут вообще, либо будут обработаны самой fmt.Println и не дойдут до пользователя (я про EINTR в первую очередь, пользователя обёрток практически никогда не заморачивают обработкой этой ошибки)? Что она вообще вернёт конкретно и будет ли она возвращать одинаковой результат для схожих ошибок на Windows и linux?

                            0
                            Не очень понял зачем и кому вы задаёте эти вопросы. Единственная догадка это то, что вы таким образом намекаете, что ответы на эти вопросы должны быть в сигнатуре функции.

                            В вышеприведённом примере понятно, что Println может вернуть ошибку записи в stdout. Этого в 90% случаев достаточно, чтобы понять, как реагировать на данную ошибку. Работа со стандартными дескрипторами в posix это знакомая концепция, поэтому легко сделать вывод, что если произошла ошибка записи в stdout, то программа мало что может тут сделать. Поэтому в подавляющем большинстве практических случаев совершенно не важно, какой из 23 ошибок может быть возвращаемая ошибка в Println, и, учитывая крайнюю редкость ситуации, её есть смысл игнорировать.

                            Это называется практический опыт и здравый смысл. Если вам нужно копать глубже и для вашей программы действительно важно среагировать на закрытый дескриптор иначе, чем на отсутствие памяти – простыми движениями вы сможете эту информацию найти, спасибо godef и gocode. В Go почти везде используется оптимизация по принципу Парето – дефолтные значения и дизайн заточен под 80% случаев, для остальных 20% есть способы копнуть глубже.
                0

                del

                  +4
                  On Error Resume Next
                    +10
                    Больше похоже на ON ERROR GOSUB.
                    +7
                    catch (error) {
                    ...handle error...
                    } try {
                    ... do something...
                    }

                    чутка непривычно, но я смогу с этим жить.
                      0
                      Исключения мало что общего имеют с этим. Явная проверка ошибок, отсутствие stack unwinding. Роднит лишь прыжок в общий блок обработки. В Go просился синтаксический сахар и это один из его вариантов. Наиболее близкий аналог это ошибки в Swift, где, несмотря на try/catch, с исключениями тоже ничего общего.
                        +1
                        Абсолютно согласен, это совсем не исключения.
                      0
                      Мне, как разработчику на go, очень не хватает како-то модификатора функции, или макроса, например, чтобы:

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

                      2. на этапе компиляции указывать компилятору закрывать все открытые ресурсы после завершения функции

                      под завершением работы функции имею ввиду любой завершение, паник, корректное (или возврат ошибекИ)
                        +1
                        Вроде defer должен решить вашу проблему :)
                          0
                          посмотрите на runtime.SetFinalizer
                            0
                            Финализаторы вроде как крайне не рекомендуют. Тут про C#, но многое применимо и к Go.

                            Я бы использовал defer, как рекомендует коллега выше.
                          –1
                          handle err {… } это возрожденный ON-unit из PL/I? Казалось бы отцы-основатели структурного программирования высмеяли такие штуки навсегда, но нет.
                            +4
                            Хоть я и являюсь сторонником исключений и считаю их самым удобным способом обработки ошибок, которое придумало человечество, но в принципе этот сахарок пожалуй достаточно приятен, чтобы Go для меня стал юзабелен. Ещё бы стектрейсы в стандартные ошибки добавили и удобный chaining, использовал pkg.errors для этого, но это должно быть в стандартной библиотеке, это база.
                              +1
                              Расширить функциональность ошибок тоже входит в их планы и описано в черновике по-соседству
                                0
                                Да, это будет в следующей статье.
                                +2
                                Чем так хороши исключения? Систему типов обходят (по факту это просто дополнение множества возвращаемых значений функции), где находится хендлер — непонятно, и статически это не выведешь (прям как goto).

                                Нет, конечно, ошибки разные бывают, и ошибки уровня «нарушен контракт», «во внутренней для модуля функции нарушены инварианты, которые должны быть заинфоршены вызывающей функцией», «не могу прочитать из файла [в высокоуровневом коде, который предполагает, что из файла всегда прочитать можно]», и так далее, как раз исключениями обрабатывать удобно, но это ближе к panic в терминах Go и Rust.
                                • UFO just landed and posted this here
                                    +1

                                    Проверяемые исключения — скорее сахарок над чем-то вроде Either (Ex1 :+: Ex2 :+: ... :+: ExN) Result, по крайней мере, такой взгляд на них, ИМХО, консистентнее.


                                    Но это уже больше вопрос терминологии.

                                    • UFO just landed and posted this here
                                +2

                                От слова check рябит в глазах

                                  0
                                  Так что пока неизвестно, будет ли это Go 1.34 или Go2. Сценария Python 2/3 не будет железно.

                                  Это значит что они планируют сохранить обратную совместимость?
                                    0
                                    Да, это приоритет номер 1 во всех этих изменениях.
                                    0
                                    Расскажите им про монады что ли…
                                      0
                                      Для этого дженерики нужны, а мы все много раз слышали, что в Go они не нужны.

                                      А, стоп, в Go 2 будет? Как же так?
                                        –1
                                        Толстенько. Они действительно не особо нужны, когда не теории на бумаге рисуешь, а код пишешь. Go дает все необходимое из коробки и спокойно так десять лет прожил, отвоевав себе приличный кусок рынка. Авторы языка самой идее никогда не противились и с самого начала хотели добавить, но должной реализации не было. Сейчас есть куча разных предложений, но все имеют свои плюсы и минусы. Поэтому вопрос дженериков опять поднят прямо как при создании Go 1, но они могут и не появиться. Авторы и комьюнити не находятся в отчаянном положении, лишь бы добавить какую-то реализацию. Ничего не понравится — ничего не добавят. Может зато потратят время на другую идею, т.к. в Go 2 авторы менять сразу много тоже не хотят. 2-3 крупных изменения, а изменений на предлагали полно.
                                          0
                                          Ну даже написали почему не добавили generics — golang.org/doc/faq#generics
                                          Ниже там и про exceptions, assertions, etc.
                                            0
                                            Дак кто ж это читает. Язык не интересен настолько, чтобы разобраться, но настолько, чтобы сраться в комментах. Ситуация знакомая, так что лицемерить и не буду даже. По-хорошему, авторы дали ответ наверное на все претензии к языку. Особенно почему нет той или иной фичи из языка Х
                                            0

                                            И списками вы, наверное, тоже не пользуетесь. Не нужны ведь.

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

                                                Ну, словари и слайсы — это дженерики. Просто авторы Go могут в дженерики, но другим не дают.


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

                                                  0
                                                  Вы прочитайте еще раз мой пост выше. Я написал все тоже самое.
                                                  +1
                                                  Если речь именно о связных списках, то надобность их в современном мире стала практически нулевая.

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

                                                Видимо, я код не пишу. Или он на самом деле на бумаге рисуется, не знаю.


                                                Увы, у меня сходу не получилось спросить у гитхаба, в скольких строках кода встречается interface{} (он почему-то скобочки игнорирует) — а это хороший кандидат на первое приближение к тому, насколько востребованы дженерики.

                                                  –1
                                                  а это хороший кандидат на первое приближение к тому, насколько востребованы дженерики.

                                                  Плохой. Это, скорее, прокси к показателю того, как плохо люди умеют маппить ментальные абстракции на системы типов.


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


                                                  type Direction Vector3
                                                  type Energy Vector3
                                                  ...

                                                  и как это кардинально упростило работу, уменьшило ошибки и повлияло на API пакетов (он еще сказал, что всегда считал такое определение типов бесполезной вещью).


                                                  И, вот, если подумать, то что 90% использования interface{}, что Vector3 в этом примере, что дженерики (в большинстве своём) – это проблема из одной плоскости: не умения чётко описывать проблемную область на языке типов данного языка программирования. Как можно догадаться, одни языки этому помогают, другие мешают.


                                                  Обобщать (generalize) легче, чем чётко раскладывать проблемную область по полочкам и описывать каждую абстракцию своим типом. Поэтому, если люди приходят с других языков и используют interface{} вместо того, чтобы правильно описывать типы, это скорее PTSD от других языков, а не признак востребованности дженериков.


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

                                                  • UFO just landed and posted this here
                                                      0
                                                      Только синглтоны — это очень больно, а по-настоящему типобезопасный код иначе не пописать пока что.
                                                        0
                                                        Можете объяснить, каким образом «достаточно обобщённых компонентов» решает фундаментальную задачу транслирования ментальной модели на код, о которой я говорил?
                                                  • UFO just landed and posted this here
                                                      0
                                                      Может тогда лучше на C# посмотреть как одну из самых успешных реализаций? Чего сразу неудачи Java вспоминать.
                                                      • UFO just landed and posted this here
                                                +2
                                                По примерам в статье складывается ощущение, что вместо check/handle достаточно было повторить для Go-шного defer идею D-шного scope(exit/success/failure). Т.е. чтобы можно было писать defer(success) и defer(failure) в дополнение к нынешнему defer. Тогда можно было бы продолжать использовать существующий механизм обработки ошибок, но при этом делать какие-то специфические действия при выходе из-за ошибки (удалять ненужные файлы, например).
                                                func CopyFile(src, dst string) error {
                                                    r, err := os.Open(src)
                                                    if err != nil {
                                                        return fmt.Errorf("copy %s %s: %v", src, dst, err)
                                                    }
                                                    defer r.Close()
                                                
                                                    w, err := os.Create(dst)
                                                    if err != nil {
                                                        return fmt.Errorf("copy %s %s: %v", src, dst, err)
                                                    }
                                                
                                                    defer(failure) os.Remove(dst);
                                                
                                                    if _, err := io.Copy(w, r); err != nil {
                                                        w.Close()
                                                        return fmt.Errorf("copy %s %s: %v", src, dst, err)
                                                    }
                                                
                                                    if err := w.Close(); err != nil {
                                                        return fmt.Errorf("copy %s %s: %v", src, dst, err)
                                                    }
                                                }

                                                  +1
                                                    0
                                                    продолжать использовать существующий механизм обработки ошибок

                                                    В нем и проблема. Defer при ошибке это бонус предлагаемого решения. У других предложений такого бонуса нет. Основные требования — уменьшить кол-во кода на обработку ошибок, сохранить все преимущества текущего подхода, упростить добавку контекстной информации в ошибки. Ваш пример ничего этого не решает.
                                                      0
                                                      В текущем механизме обработки ошибок в Go со стороны видится две проблемы*:

                                                      1. Многословность проверок кодов ошибок.

                                                      2. Сложность с написанием кода по очистке ресурсов и/или откату каких-то операций при обработке ошибок.

                                                      Первая проблема может быть решена тем или иным синтаксическим сахаром. Например, использованием ключевого слова check или префикса/суффикса '?'. Вроде такого:
                                                      w := check os.Create(dst)
                                                      // или
                                                      w := ?os.Create(dst)
                                                      


                                                      Вторая проблема решается за счет defer(success/failure).

                                                      * По поводу «проблем». ИМХО, своим успехом Go обязан именно такому вот примитивному и прямолинейному коду, который не требует высокой квалификации от разработчиков и делает код разных людей максимально однотипным. Так что, что кажется проблемой, ИМХО, на самом деле является одной из важнейших составляющих привлекательности Go в современном мире.
                                                        0
                                                        Сложность с написанием кода по очистке ресурсов и/или откату каких-то операций при обработке ошибок

                                                        Если честно, эту проблему я слышу сейчас первый раз. Я давно слежу и участвую в дискуссиях по поводу ошибок в Go 2, но ниразу я не встречал именно эту проблему. Да и на практике тоже.
                                                          0
                                                          Если честно, эту проблему я слышу сейчас первый раз.
                                                          Значит вы не читали обсуждаемую статью, ибо в разделе «В чём проблема с обработкой ошибок в Go?» об этом и идет речь. См. пример из этого раздела, в котором os.Remove() нужно вызывать в двух if-ах. Это оно и есть.
                                                            0
                                                            Статью я читал. Я говорю о том, что было раньше. Обсуждение предложений для Go 2 началось намного раньше. Еще раньше народ просто в бложиках постил, чего им в языке не нравится. И вот эта проблема встречается мне первый раз сейчас. Она может быть где-то и встречалась, но намного реже. Вся критика все это время была направлена именно на многословность. Поэтому и удивило, что сейчас внезапно это всплыло как одна из проблем языка.

                                                            Я даже на практике не помню проблем подобных. Удалить файл при ошибке — ерунда, это не требует изменений в языке. В том же самом defer можно банально проверить наличие ошибки и выполнить нужный код.
                                                              0
                                                              Я даже на практике не помню проблем подобных. Удалить файл при ошибке — ерунда, это не требует изменений в языке. В том же самом defer можно банально проверить наличие ошибки и выполнить нужный код.
                                                              Ну значит вообще весь этот огород с handle err не нужен, если по вашей практике судить. Достаточно лишь ввести конструкцию, которая будет аналогом Rust-овских try! и '?'. Делов-то.

                                                              Вы это Google-овцам расскажите, а то они не знают, что на практике проблем нет, выдумывают какие-то handler-ы.
                                                      0

                                                      А defer(failure) можно реализовать через проверку:


                                                      defer func() {
                                                          if err != nil {
                                                             ...
                                                          }
                                                      }
                                                      +2
                                                      Я пишу на с++, на го не пишу, но периодически почитываю статьи про другие языки, особенно про такую важную тему как обрабтока ошибок. Мне это новая обработка ошибок на го очень сильно напоминает с++ on_scope_exit концепцию/семейство функций. Ваш хендл это on_exception ваш дефер это on_scope_exit. Осталось добавить on_success аналог дефер который вызывается только если не было ошибок и относиться к проверяемым ошибкам как к эксепциям т.е. если функция вернула ошибку и она была вызвана с чеком то вызывать все подряд (дефер/хэндл) в порядке обратном объявлению. Дефер и хендл суть одно и тоже только дефер более общий случай, вызывается всегда неважно есть ошибка или нет. Нет смысла городить отдельные (от дефер) правила порядка вызовов для хендл.

                                                      Кому интересны подробности из первоисточника и кто не знаком с с++ и/или концепций on_scope_exit гуглите по Андрей Александреску с++ декларативное программирование. Я смотрел/читал все на английском поэтому не уверен, что мой русский перевод нагуглиться. Вот как раз местный пост кому лень гуглить.
                                                        0
                                                        Вы можете написать блог пост и добавить в вики с отзывами, там и расскажете авторам Go, что нет смысла городить отдельные от дефер правила для хендл. )
                                                          +1
                                                          Мне инетерсна тема обработки ошибок и поэтому я написал этот коментарий здесь, но у меня нет ни одного стимула помогать развитию го и поэтому я не собираюсь ничего добавлять в указанное вики. Нужно понимать что просто заметка в вики скорее всего ничего не способна изменить. Что бы реально на что то повлиять человек должен быть готов долго и нудно отстаивать превосходство своих идей над альтернативами, а это очень тяжелый труд.
                                                            0
                                                            Видимо недостаточно она вам ещё интересна. :)
                                                          0

                                                          Вас не смущает, что defer и handle имеют разные сигнатуры, да и семантика отличается?

                                                            0
                                                            Нет, не смущает. У дефер и хендл одинаковые сигнатуры — нет сигнатуры. Сигнатура есть тогда когда вы через возможности языка можете ее изменить, если вы не можете ее изменить значит сигнатуры нет (и не важно как оно реализованно под капотом). Семантика отличается несущественными деталями. Дефер — выполнить что то на выходе из скоупа. Хендл — выполнить что то на выходе из скоупа и наличии ошибки. Как можете видеть хендл это частный случай дефер.

                                                            В с++/ди для проброса ошибки внутрь дефер/хендл используются техника раскрутки стека при эксепшене в го такого механизма (пока) нет. Вместо этого я полагаю (спецификацию не читал могу ошибаться) в го идиома возврата кода ошибки как последнего значения в тупле скорее всего поддерживается на уровне компилятора путем размещения значения ошибки в регистре ЦПУ (как очень горячих данных). Следовательно нет вообще никаких проблем передать это значение внутрь хендл (оно уже по сути там в определенном регистре), а остальные данные при необходимости могут быть переданы через стэк. Опять же не знаю точно, но как я понял в го нет деструкторов и этот факт значительно облегчает реализацию этой новой концепции обработки ошибок. По сути она тривиальна. Весь код из дефер/хендл пишится в конце скоупа с разными метками входа в соответсвии с порядком объявления. Далее если основной код завершился без ошибок то регистр с ошибкой содержит 0 и выполняется только код соответсвующий дефер секциям. Весь код хендл условный т.е. если регистр с ошибкой не 0 то выполняем код из хендл секции иначе не выполняем. Также выражение check XXX разворачивается во что то наподобие

                                                            result, err = XXX()
                                                            if (err != nill)
                                                               goto end_of_scope_N
                                                            

                                                            где end_of_scope_N метка соответсвующая одному из входу в зависимости от порядка объявления дефер/хендл.

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

                                                          Теперь в самом простом языке 3 разных вида обработки ошибок, ни один из которых не является универсальным. Defer будет использоваться в случае, когда действие нужно выполнить вне зависимости от успешности (аналог finally), handle — когда приборка отличается в случае успеха и неудачи. Ну и старая добрая проверка err на nil никуда не денется, так как check подразумевает не обработку ошибки, а проброс вверх по стеку, если некоторая ошибка восстановима, то check не подходит. Особую прелесть добавляет факт, что defer и handle похожи, но заметно отличаются, один дружит с паникой, другой — нет, разно ведут себя в циклах, поэтому совершенно непонятно, автор использовал defer потому, что ждёт панику или просто потому что так писать короче.
                                                          Кроме того, в любой более-менее серьёзной функции ошибка будет одной из множества, и они будут обрабатываться по-разному, файл не найден, тогда пробуем по другому пути или создаём, или файл создан в более новой версии и нужно отказаться трогать чтоб не испортить данные. Соответственно нужно писать ручную проверку типа ошибки. Ну вот написали мы проверку, как быть в ветке с необрабатываемой ошибкой? Просто вернуть err? Тогда не вызовутся уже установленные хэндлеры. Выполнить check err? Отличная идея, так и нужно делать… Вот только нам же обещали отсутствие ситуации питон 2 vs 3, код должен быть совместимым, добавляя свой хендлер в начале функции нужно сначала посмотреть, нет ли где в теле выхода с ненулевым err, а то хендлер проигнорируется.


                                                          В общем этот го не получился. Выбросите и сделайте новый.

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

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

                                                            Но вы также поднимаете и реальные проблемы — совместимость со старым кодом. Думаю хорошим рабочим решением будет ворнинги компилятора детектирующие описанные вами кейсы так, что го еще рано закапывать, хотя персонально я разделяю ваше оценочное суждение по поводу качества го в целом как языка.
                                                              +2
                                                              Не согласен. Текущее предложение наоборот, помогает не обрабатывать ошибки. Облегчение проброса наверх — хорошее дело, код не так замусорен, кроме того, необходимость писать после каждого вызова if err != nil немного препятствует декомпозиции, зачем выносить 4 строки в отдельную функцию, если вызов этой функции с последующей проверкой ошибки займёт те же 4 строки. Тем не менее, именно обработка ошибок ничуть не улучшается. Для обработки потребуется if или свитч по типу ошибки и гоу не подскажет в случае пропущеного варианта, в этом плане джава с её проверяемыми исключениями лучше. Гоу фактически стал аналогом других языков, где проверка ошибок сводится к ловле любых исключений на верхнем уровне.
                                                              С ворнингами или линтером тоже непонятно, вот, скажем, у меня стоит свитч по типу ошибки, в одной ветке я ошибку исправляю и продолжаю дальше, в другой я выполняю check err, т.е. вызываю обработчики и пробрасываю наверх, а в третьей просто пишу «return nil, err» или «return nil,OuterError(err)». Идеальный случай для ворнинга. Но по факту возможно что это старый непроверенный код, или мне просто не нужен обработчик в этом случае. В общем чую появится специальный комментарий, отменяющий предупреждение в данном случае.
                                                              Ну и отсутствие унификации тут не то что бы главное. До этого была концепция «ошибка — это просто один из видов данных». У такого подхода свои недостатки, но есть и достоинства (наверное есть). Теперь же err больше не последнее значение в возвращаемом кортеже, а некий благословенный элемент кортежа, каким до этого было исключение. Только с дырой в виде обработчиков, которые могут не вызваться. Получается как в анекдоте «не кажется ли тебе, Билл, что мы забесплатно дерьма поели».
                                                            0
                                                            Если говорить в множестве вот таких кусков:

                                                                r, err := os.Open(src)
                                                                if err != nil {
                                                                    return err
                                                                }

                                                            То я бы хотел иметь возможность написать в одну строку примерно так:

                                                             r, err := os.Open(src) try ("blah-blah: %v", err)

                                                            Вместо «try» поставьте любое красивое и подходящее слово.

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

                                                            Ещё более коротко (без добавления некоей обработки ошибки):

                                                             r, err := os.Open(src) try
                                                              +2
                                                              Есть реальная возможность повлиять на дизайн:
                                                              github.com/golang/go/wiki/Go2ErrorHandlingFeedback

                                                              Хотя уже было похожее предложение: github.com/golang/go/issues/21161
                                                                0
                                                                Есть реальная возможность повлиять на дизайн:


                                                                Вы, предположу, не подписаны на кейсы по обработкам ошибок и генерикам.
                                                                Гугл в очередной раз всех поимел сделал все по своему (как с vgo vs dep).
                                                                Ну и удивительно, что они выбрали такой фидбэк от коммьюнити а не вообще обычную почту.
                                                                  +1
                                                                  Что, простите?
                                                                    0
                                                                    На дизайн не повлиять — гугл выкатил и после «обсуждения» просто сделает это.
                                                                    Постить ссылки в вики безполезно — гугл второго раунда делать не станет.
                                                                    Точно также как было с «обсуждением» vgo.
                                                                    Так называемому коммьюнити politely дают возможность промеж себя пообщаться и кушать, что дают. В кейсах по этим пропозалам гугловцев не было и они никаких хинтов там не постили.
                                                                      +1
                                                                      сегодня видел статистику — за второй квартал 2018 года коммитов в Go от не-гуглеров больше чем от гуглеров.
                                                                        0

                                                                        И это ничего не меняет.
                                                                        Гугл имеет свой интерес и профит и все решения принимает сам. Да они скорее всего пистонов отхватили за то как vgo выкатили, и теперь все могут аж напихать ссылок. Они даже в оригинальных кейсах линки на пропозал не воткунли. Wtf?

                                                                          0
                                                                          Ухты, conspiracy theories у нас ещё не было. Продолжайте)
                                                                          0
                                                                          Давайте я вам про type aliases еще напомню. Вот где был заговор всемирный.
                                                                            0
                                                                            Хахаха — ты про эти два кейса? github.com/golang/go/issues/16339
                                                                            github.com/golang/go/issues/18130 — так это только подтверждение что фидбэк им только мешает — изза публичной дискуссии они релиз пропустили.
                                                                              –1
                                                                              Тоесть вы сейчас выискиваете по issues все случаи, когда Go team не согласился с предложенным изменением языка, и этим доказываете свою теорию заговора? Ок.
                                                                                0
                                                                                Wat?!
                                                                                Тоесть эти два «не связанные» пропосала внесла не го тим и даже не гуглеры?!
                                                                                И фича гуглу не нужна была вовсе?
                                                                                И релиз они не пропустили?
                                                                                А форсить пользователей постить линки на вики страничке (где подписаться на изменения нельзя) это несомненно улучшение процесса?!
                                                                                  0
                                                                                  Мне очень сложно понять, что вы пытаетесь сказать. Я же не могу думать, что вы пытаетесь с помощью cherrypicking-а доказать какую-то точку зрения – это было слишком оскорбительно так думать о Вас. Но пока что сложно понять, что вы хотите донести.
                                                                        0
                                                                        Я понял ваше мнение, но хорошо зная многих людей и из Go команды и из коммьюнити, я не вижу ни единого подтверждения вашим словам. История vgo vs dep, которую вы так удобненько пытаетесь представить в виде доказательства, совершенно тут не к месту, в ней своя история и свои проблемы, и мы можем на эту тему пообщаться, если хотите.
                                                                        Хотите верить, что давать конструктивный фидбек, когда его просят – бесполезно: пожалуйста. Только не подавайте это как какой-то факт, и уж тем более, не притягивайте за уши аргументы, о которых другие люди более осведомлены.
                                                                          0
                                                                          Какие именно аргументы притянуты за уши?
                                                                          Что через «публичные» обсуждения их пропосалы тяжело проходят?
                                                                          Что вместо осуждения их пропосала через issue они услажняют процесс обсуждения?

                                                                          Again, I apologize for all the mistakes I made during this process. I've learned a lot about what a successful community collaboration does and does not look like, and I hope it helps the next one run more smoothly.


                                                                          Куда уж более гладко — коммьюнити в песочнице с issues играется — их мнение нам так важно, что мы знать не хотим нравится\не нравиться им то что мы предложили — пусть письменно заявления подают — мы несомненно их рассмотрим.
                                                                            –1
                                                                            Что вместо осуждения их пропосала через issue они услажняют процесс обсуждения?

                                                                            А как надо обсуждать? Если у вас больше опыта в развитии нового языка и коммьюнити, напишите как нужно – если ваш подход будет лучше, то все прислушаются.=
                                                                +1
                                                                Я бы все же предложил явное указание какой хендлер какому check будет соответсвовать, в функциях с кол-вом хендлеров больше одного. А то так будет сложно отыскивать ближайший блок обработки
                                                                  +2
                                                                  Так предлагайте. Есть реальный шанс повлиять на дизайн же.
                                                                  github.com/golang/go/wiki/Go2ErrorHandlingFeedback

                                                                  Кстати, я уже встречал такое предложение в одном из отзывов.
                                                                    +1
                                                                    Просмотрел фидбек и здесь уже есть подобные предложения. Понравилось вот это, особенно вторая часть, когда вместо имени переменной ошибки подставляется имя хендлера
                                                                  –1
                                                                  if result, err = funcName(); err == nil {
                                                                  //DO SONTHING
                                                                  } else {
                                                                  fmt.Println("Error:", err)
                                                                  }
                                                                    –2
                                                                    Так и не пойму, зачем мучить хомяка. Ну не завезли нормальных исключений изначально — бывает, так ведь дело поправимое.
                                                                    Легаси библиотеки никому переписывать не хочется — это понятно. Можно было бы добавлять «check» или что-то подобное перед функциями, ошибки которых хочется выбрасывать исключениями, а дальше: try, catch, finally — все как у людей.
                                                                      0
                                                                      «Не завезли» исключения по причинам уже озвучинными авторами: golang.org/doc/faq#exceptions. И check/handle вовсе не возврат к исключениям.
                                                                        +2
                                                                        Краткий перевод:
                                                                        «Нам кажется, что правильное использование проверенной временем конструкции „try-catch-finally“ наш бородатый контингент не осилит и наговнокодит на Гошке так, что все шишки опять полетят дизайнерам языка (а далеко не все из шишек нам по вкусу!).

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

                                                                        Мы пойдем своим путём. Для обработки обычных ошибок, пожалуйста, используйте возможность возврата множества значений из одной функции (заодно подразобьёте все свои if'ы на присвоение/проверку, Гошка проще всех, вы не знали?).

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

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

                                                                        Мы уже завезли Defer, Panic, Recover и планируем продолжать удивлять вас количеством и разнообразием способов делания одинаковых вещей.

                                                                        Великолепие Гошки в обработке ошибок вы в полной мере оцените после пары-тройки серьезных проектов (*демонический смех)

                                                                        Вкусного вам кофе, держитесь там,
                                                                        любящий вас в мыслях
                                                                        авторский коллектив.»
                                                                          0
                                                                          Ну, перевод немного странный. А вы, стесняюсь спросить, в каком языке программирования практикуете?
                                                                            0

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


                                                                            Особенно после современных плюсов, где вполне легко делается аналог Either.

                                                                              0
                                                                              Да ладно Вам стесняться!
                                                                              Я — человек широких взглядов, практикую на чем придётся, в соответствии с требованиями проекта. Прилично налюбился с явой, плюсами и чистым си; по вебу, в основном, бывают: питон, нода и пхп с яваскриптом.
                                                                              Гошка, кстати, хорош, когда дело касается несложного, но нагруженного бэкенда, сетей, внутрипротокольных блужданий. Критикую я его редко, по делу и для смеха.
                                                                              Но когда хайпанутому клиенту стукнет «вот прям всё переписать на го!» — это явный перебор и потеря времени, как по мне. Стараюсь образумить, выходит не всегда.
                                                                        +3

                                                                        Теперь то можно встать в полный рост и сказать "а я же говорил".


                                                                        Ну и как обычно


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

                                                                        Нет, это не проблема исключений, правда. В java такой проблемы, например, нет и всегда понятно, какое исключение может выбросить функция (исключая Runtime, но и panic в go есть).


                                                                        А любителям рассказывать, что вот для java нужно ide, а для golang — нет, можно я напомню, что у go с этим делом еще хуже в силу того, что существует неявный импорт всех модулей из папки и в целом импорт сразу всего, а не по деталям в моде. Из интерфейса github код на go очень больно читается из-за этого.

                                                                          0
                                                                          Ну и как уже отметили — очень круто, что наконец-то начали думать про лишний текст)
                                                                            –5
                                                                            Теперь то можно встать в полный рост и сказать «а я же говорил».

                                                                            Ха. Ну да, вместо того, чтобы давать конструктивный фидбек и писать experience reports, которые повлияли на развитие Go и привели к появлению данного черновика, вы, в очень, мягко говоря, не конструктивной манере, рьяно комментировали на Хабре. Упустили шанс сделать мир лучше, поздравляю.
                                                                              0
                                                                              Ха. Ну да, вместо того, чтобы давать конструктивный фидбек и писать experience reports, которые повлияли на развитие Go и привели к появлению данного черновика, вы, в очень, мягко говоря, не конструктивной манере, рьяно комментировали на Хабре. Упустили шанс сделать мир лучше, поздравляю.

                                                                              А как там такой же репорт по поводу дженериков практически на заре go? Или я что-то путаю?

                                                                                –1
                                                                                Не очень понял вопрос.
                                                                                  0

                                                                                  Если я не ошибаюсь, где-то для версии go1.5,go1.6 кто-то написал очень хороший propasal по дженерикам, на что был большой ответ в google docs где подробно объяснялось почему "это не нужно".


                                                                                  Или я что-то путаю?

                                                                                    –1
                                                                                    Первый раз слышу. Ссылки?
                                                                                      0

                                                                                      Если я не ошибаюсь, вот этот документ. Вроде как он появился раньше 2016 года (если судить по issue и я вполне могу ошибаться). Довольно подробный документ по generiс в целом.


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

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

                                                                                        Каким образом вы его трансформировали в «где-то для версии go1.5,go1.6 кто-то написал очень хороший propasal по дженерикам, на что был большой ответ в google docs где подробно объяснялось почему „это не нужно“.» – для меня загадка, но это очень хорошо иллюстрирует суть всех дискуссий с Вами.
                                                                                +8
                                                                                Простите, но давайте сравним.

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

                                                                                По итогу комьюнити/коре-тим таки пришло к выводу, что проблема есть. Кто сделал полезное дело, SirEdvin, призывающий решить проблему, или divan0, закрывающий на нее глаза?
                                                                                  0
                                                                                  SirEdvin — постоянно озвучивал, что есть проблема, но не предлагал конкретных решений.
                                                                                  divan0 — постоянно утверждал, что никакой проблемы нет, все хорошо.

                                                                                  Я ваши комментарии тоже помню, поэтому не ожидаю объективности, но, справедливости ради, SirEdvin «постоянно озвучивал», что в Go плохо всё и атаковал без разбору все аспекты языка – от GOPATH до интерфейсов и до отсутствия исключений. Ну, знаете, тот случай, когда предмет обсуждения не важен, а важен сам факт критики. Мои комментарии были парированием его утверждений, поэтому вам могли они выглядеть как «утверждения, что никакой проблемы нет». Другими словами, когда собеседник делит тему на белое и чёрное, то аргумент «нет, оно не чёрное» не означает, что это «белое». Это классическая fallacy of grey.

                                                                                  Я, кстати, по прежнему считаю, что явная проверок ошибок на порядок лучше исключений. К вышеприведенному дизайну у меня двоякие чувства – с одной стороны, виден очевидный плюс, с другой – это усложнение языка, чуть более «магии» и т.д. Но, посмотрим, как дальше пойдет процесс.
                                                                                    +2
                                                                                    атаковал без разбору все аспекты языка

                                                                                    А как называется такая логическая ошибка, когда вы перекручиваете утверждение и приписываете мне то, что я не говорил?
                                                                                    Изначально мне в го не нравились:


                                                                                    1. Обработка ошибок (и ее фиксят)
                                                                                    2. Отсутствия дженериков (и как следствие, я писал, что все используют вместо них interface, но нападать на интерфейс как-то… странно, и я такого не помню).
                                                                                    3. Идеи с окружением (GOPATH, версионность по коммитам вместо нормальный пакетов), и это фиксят
                                                                                    4. Идеи с тем, что комментарии можно спокойной использовать как метаинформацию без отделения специальным синтаксисом. И в этом я был прав, у go теперь есть прекрасная easyjson и писать комментарии на go стало еще немного страшнее).

                                                                                    Я что-то еще забыл?

                                                                                    +1
                                                                                    SirEdvin типичный троль, его цель тут просто набрасывать. При этом человек рассуждает на счет concurrency в Go, даже не понимаю что-то такое многопоточность, говоря, что «в реальности вместо каналов в Go будет использоваться внешняя очередь типа NATS».
                                                                                      +1

                                                                                      Вырывать комментарии из контекста не очень красиво.


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

                                                                                        0
                                                                                        Мы разговаривали не про какие-то абстрактные воркеры, а про горутины.
                                                                                        А вот ваш комментарий
                                                                                        А еще обратно к реальному миру, мне кажется, вместо каналов вы чаще будете использовать какие-то другие MQ, например nats.
                                                                                          0
                                                                                          Создается 10 goroutine, которые читают с одного канала и обрабатывают сообщение. Есть рутина, которая пишет в канал (не важно как, например, читает с файла и пишет в канал). Обработка сообщений затратный процесс (потому один пишет и много читают). Самый обычный кейс.
                                                                                          При этом, после Ctrl+C завершается работа всех goroutine и после этого приложение останавливается.

                                                                                          А вот ваша задача. Я воспринял это как опять же паттерн "мастер ставит задачи — воркеры выполняют". Поэтому и сказал о внешних очередях.

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

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


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

                                                                                                +1
                                                                                                Это тут причем?
                                                                                                Мы говорили про concurrency в Go. Вы сказали, что в питоне не хуже, потом привели пример с IPC и процессами.
                                                                                                  0
                                                                                                  Очевидно, потому что я немного неправильно выражаю свои мысли. Ну и еще немного неправильно в целом думал, вы меня поправили.

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

                                                                                                  Скобочки я расставил для себя, что бы убедится, что опять не напутал термины и вы меня правильно поймете.
                                                                                                    0
                                                                                                    Мы можем конечно повторить разговор — вы покажете, как сделано concurrency в питоне (с IPC и процессах), я скажу что это костыли, а вы, что «мне кажется, вместо каналов вы чаще будете использовать какие-то другие MQ, например nats.»
                                                                                                      +1

                                                                                                      Ну, это костыли, которые призваны решить проблемы, с которыми эти конкретные костыли еще не справились. Я так же мог использовать треды в python и in_proc из zmq, если бы в python треды работали и было бы почти без костылей. Поэтому и живем на процессах, да.


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


                                                                                                      Офф-сайд: некоторые опытные люди, например, автор fasthttp предлагают в go так же запускать по процессу на процессор (в README написано, что на ядро, но в telegram чатике go вызвали вроде как core-разработчика и он пояснил, что это старая информация и имеет смысл только в том случае, если у вас несколько процессоров, прирост почти 15-20%)

                                                                                                        0
                                                                                                        Но в моем исправленном тезисе вопрос был про удобство, а как я понимаю, эти костыли в целом влияют на производительность.

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


                                                                                                        Офф-сайд: некоторые опытные люди, например, автор fasthttp предлагают в go так же запускать по процессу на процессор (в README написано, что на ядро, но в telegram чатике go вызвали вроде как core-разработчика и он пояснил, что это старая информация и имеет смысл только в том случае, если у вас несколько процессоров, прирост почти 15-20%)

                                                                                                        Вы сами хоть читаете ссылки, что постите?


                                                                                                        Use Go 1.6 as it provides some considerable performance improvements.
                                                                                                      +1
                                                                                                      Более того, в более других языках комплиятор может вам много чего интересного гарантировать на тему параллельных (детерминизм, например) и конкурентных (отсутствие рейсов и дедлоков) вычислений. И это не случай Go.
                                                                                      +1
                                                                                      Чтобы писать experience reports, нужно обладать некоторым experience. А если знакомство с языком заканчивется на чтении примеров кода, то писать по этому опыту experience reports несколько, гм, странно. Ну, на мой взгляд. Может, там и приветствуется такое, не знаю.

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

                                                                                      Ожидать и того, и другого от всех (особенно от тех, у кого знакомство с языком, опять же, закончилось на чтении примеров) несколько, скажем так, странно.
                                                                                        –4
                                                                                        Спасибо за такое детальное пояснение, кэп. Если вы им пытаетесь объяснить почему отдельные люди, не имея опыта и квалификации, обладают мотивацией чтобы писать сотни комментариев, с пеной у рта рассказывая, какой плохой язык Go, но не могут писать конструктивную критику, то у вас получилось. Теперь понятно.
                                                                                        • UFO just landed and posted this here
                                                                                      –2
                                                                                      В java такой проблемы, например, нет и всегда понятно, какое исключение может выбросить функция

                                                                                      Ну да, поэтому в большинстве Java программ просто выбрасывается General Exception и ловится в самом верху – всегда понятно, какое исключение :)
                                                                                        0

                                                                                        А go вместо General Exception у вас есть error и ничего не поменялось. И на java, и на go у программистов есть все возможности нормально разграничить ошибки по типам и сделать их грамотную обработку. Но почему-то все равно везде чистые error и обработка ошибок где-то на самом верху.


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

                                                                                          –1
                                                                                          Но почему-то все равно везде чистые error и обработка ошибок где-то на самом верху.

                                                                                          Ваше утверждение не верно и кодом на практике не подтверждается. Обработка ошибок всегда в месте их выброса. Конкретные error, а не просто строкое значение, нужны очень редко и используются, когда это необходимо. Go никак это не заставляет делать (можно вообще ошибку игнорировать и никто не скажет ничего), эту проблему я в предложениях озвучивал на гитхабе. К счастью, команда Go изначально озвучила best practices и программисты в своем подавляющем большинстве их соблюдают. Программисты ленивые, когда им нужно менять свои привычки. Тут же привычка была привиты изначально.
                                                                                            0
                                                                                            Ваше утверждение не верно и кодом на практике не подтверждается. Обработка ошибок всегда в месте их выброса

                                                                                            У меня есть два пруфа:


                                                                                            1. Почитайте в этой статье про дефолтный хендлер
                                                                                            2. Вот я открыл случайный файл в moby/moby и что же я там вижу? 4 места обработки ошибок и все только то и делают, что пробрасывают ошибку наверх. Если вы так не делаете — это круто и достойно уважения, но это не так работает.
                                                                                              0
                                                                                              В большинстве случаев проброс ошибки наверх действительно работает и ничего более делать не приходится. Но это намного лучше исключения, ибо явно от начала до конца. Все таки с ошибкой разбора JSON более ничего не сделаешь. Факт в том, что Go изначально привил best practices, и они в основном соблюдаются. Было бы лучше, если бы игнорирование ошибки было ошибкой компиляции, что я предлагал, но наверное это не сделают. Но даже так, невероятным образом это работает лучше исключений.
                                                                                                +2

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


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

                                                                                                  +1
                                                                                                  Читал достаточно кода на Go (на Java — ещё больше), имею сказать, что в Go значительно проще понять, какие ветки породили ту или иную ошибку.

                                                                                                  Тут, конечно, не только обработка ошибок, но и в целом подход к написанию программ: меньше динамики (в Java динамика — часть парадигмы языка). Но, когнитивная нагрузка при чтении исходников после введения check/handle в Go, конечно, возрастёт. Надеюсь, не сильно.
                                                                                                –7
                                                                                                Вот я открыл случайный файл в moby/moby и что же я там вижу?

                                                                                                Это называется anecdotal evidence. Не рекомендую таким образом что-то кому-то доказывать, если хотите, чтобы к вам прислушивались.
                                                                                                  +6

                                                                                                  Мне вот интересно, вы проходили какие-то курсы, как писать псевдоумные комментарии?


                                                                                                  Вы постоянно злоупротребляете практически всеми логическими ошибками, такими же anecdotal evidence и апелляциями к авторитету.


                                                                                                  Более того, абсолютно все, что вы (ну и я) пишите в обсуждениях связанных с go — является жутким субъективизмом, для которого у вас нет никакой аргументации, подкрепленной какими-либо исследованиями. То же магическое утверждение, которое мы тут обсуждаем про "модель ошибок в go заставляет программистов обрабатывать ошибки на месте", у вас есть какие-то исследования на эту тему? Правильные, с контрольной группой и прочими прелестями.


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

                                                                                                    –6
                                                                                                    > Мне вот интересно, вы проходили какие-то курсы, как писать псевдоумные комментарии?

                                                                                                    Я правильно вас понял — вы не согласились, что ваш пример про moby это anecdotal evidence и вместо того, чтобы объяснить, где я не прав, решили сказать что мои комментарии «псевдоумные»?
                                                                                                    Если какие-то «курсы» я и проходил, то исключительно по формальной логике. И ваши комментарии просто сильно выделяются обилием логических ошибок и манипуляций – от red herring (чуть выше в дискуссии с creker) до whataboutism. Кстати, о последнем – аргумент «вы тоже злоупотребляете» (вне зависимости от того, насколько он верен) это как бы оно.

                                                                                                    > апелляциями к авторитету.
                                                                                                    Appeal to authority это не логическая ошибка сама по себе. Если авторитет, о котором речь, действительно авторитет, то это легко может быть очень веский аргумент. Хотя в определенных случаях это да, может быть логической ошибкой.

                                                                                                      +1
                                                                                                      Я правильно вас понял — вы не согласились, что ваш пример про moby это anecdotal evidence и вместо того, чтобы объяснить, где я не прав, решили сказать что мои комментарии «псевдоумные»?

                                                                                                      А вы внимательно прочитали последний абзац моего комментария?


                                                                                                      Appeal to authority это не логическая ошибка сама по себе.

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


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

                                                                                                        –7
                                                                                                        практически все программирование находится вне области формальной логики

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

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


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

                                                                                                          Мне кажется, тут вполне соблюдена формальная логика.

                                                                                                            –6
                                                                                                            Мне кажется, тут вполне соблюдена формальная логика.

                                                                                                            Ухты, поздравляю.
                                                                                                              +3
                                                                                                              Ну так вы уже прочитали и признаете, что в этом случае были не правы? Или от комментариев, в которых вы упрекаете меня в отсутствии логики будете переходить к саркастическим?
                                                                                                                –7
                                                                                                                Количество derailing-а в общении с вами превышает все допустимые нормы, поэтому завершим это «общение» сарказмом, да.
                                                                                                          0
                                                                                                          Ирония состоит в том, что практически все программирование находится вне области формальной логики

                                                                                                          И тут чувакам из PLT-сообщества резко стало грустно.
                                                                                                            0

                                                                                                            Вы про них?

                                                                                                              0

                                                                                                              Про них, или про них, или про них, и так далее.

                                                                                                                0
                                                                                                                Я очень прошу у них прощения, но на мой взгляд, эти сообщества далеки понятия «заметные».
                                                                                                                  0

                                                                                                                  Это да. Но это уже следующий вопрос.

                                                                                                            +2

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


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

                                                                                                              –2
                                                                                                              В данном случае апелляция к авторитету — это демагогический приём, эксплуатирующий у людей ошибку «гугл — большая успешная корпорация,

                                                                                                              И где вы такое утверждение увидели, покажете?
                                                                                                  0
                                                                                                  Довольно часто интересует конечный результат успешного завершения всех составляющих процесса. А если упало — уже не так важно почему.
                                                                                                    0

                                                                                                    Как тот несчастный, которому приходится потом поддерживать системы, от программистов, которые думают так же могу сказать — это очень плохая и просто отвратительная позиция. У меня уже собралось штук 5-7 историй, где мне хочется убивать людей за то, что они положили болт на обработку ошибок, поставили логику "если ошибка, сказать что что-то пошло не так" и мне потом пришлось в этом добре копаться и понимать "А что же пошло не так?", потому что исправлять как-то надо.


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

                                                                                                      0
                                                                                                      Не нужно никого убивать.
                                                                                                      Идеальный программист в вакууме пишет идеальный код, всегда обрабатывает все ошибки, укладывается во все сроки и не существует.
                                                                                                      Жизнь накладывает свои ограничения.В основном, это время и деньги.
                                                                                                      Нет проблем делать что-то супер качественно, если: а) на это выделят время, б) за это заплатят деньги.
                                                                                                      Реальность в том, что в бизнесе редко кто считается с твоими (моими) личными взглядами на красоту кода.
                                                                                                      Бегать от реальности — глупо, менять её — не всегда возможно.
                                                                                                        0

                                                                                                        Есть разница между "супер качественно" и "залогировать ошибку". Если вам так сложно выбросить ошибку в лог, что вам на это нужна куча времени, вы точно делаете что-то не так.

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

                                                                                                          Если не сталкивались с ситуациями, когда она не важна — еще столкнётесь.
                                                                                                            0
                                                                                                            Мне очень сложно понять, в каких ситуациях причина падения может быть не важна.
                                                                                                            Вот у вас есть программа. Она упала. Вы ее сразу выкидываете или продолжаете с ней работать дальше? Если продолжаете работать дальше, а она опять падает, вы будет игнорировать проблему? Или как это работает?
                                                                                                              0
                                                                                                              > Или как это работает?
                                                                                                              Именно так и работает
                                                                                                  –1
                                                                                                  в большинстве Java программ просто выбрасывается General Exception и ловится в самом верху

                                                                                                  Возможно в большинстве ваших программ так и есть.
                                                                                                  Но, к счастью, вы не автор большинства программ на Java.
                                                                                                    0
                                                                                                    Разочарую, это вывод исследователей, который статическим анализом проанализировали 400к Java проектов на Github-е. Я уже когда-то тут постил ссылку на это отрезвляющее исследование, могу поискать если интересно.
                                                                                                      0
                                                                                                      Поищите, на самом деле любопытно глянуть на исследование :)

                                                                                                      Возможно вы имели в виду вот такой кейс:
                                                                                                      try {
                                                                                                         // Do something...
                                                                                                      } catch (FileNotFoundException e) {
                                                                                                        throw new RuntimeException("file is required blabla", e);
                                                                                                      }
                                                                                                      

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

                                                                                                      По сути это некий аналог
                                                                                                      err := ... // do domething
                                                                                                      if err != nil {
                                                                                                         log.Fatalf("file is required blabla: %v", err)
                                                                                                      }
                                                                                                      


                                                                                                      Вы это имели в виду, когда говорили про «General Exception»?
                                                                                                        0
                                                                                                        Под General Exception я имел ввиду просто Exception.

                                                                                                        Вот, оригинальная ссылка neverworkintheory.org/2016/04/26/java-exception-handling.html, ссылка на сам пейпер (http://plg.uwaterloo.ca/~migod/846/current/projects/09-NakshatriHegdeThandra-report.pdf) и зеркало (оригинальная ссылка умерла вроде) www.dropbox.com/s/yhd3d818hw5dv2h/p484-kery.pdf?dl=0
                                                                                                          +1
                                                                                                          Спасибо за ссылку. Выглядит действительно интересно, на досуге почитаю.

                                                                                                          Глянул на секцию Аbstract. А там пишут такое:
                                                                                                          We found that programmers handle exceptions locally in catch blocks much of the time, rather than propagating by throwing an Exception.
                                                                                                          Не кажется ли вам, что это прямо противоречит вашему утверждению «просто выбрасывается General Exception и ловится в самом верху».

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

                                                                                                            Насчёт 78% — тут даже цитата в блог посте есть:
                                                                                                            Similarly, most programmers ignore Java's carefully thought out exception hierarchy and simply catch Exception (78%) or Throwable (84%) rather than any of their subclasses.

                                                                                                            Что несколько не то, что я сказал. Теперь самому интересно найти и перечитать оригинальный пейпер, но это то, как я его тогда запомнил, да.
                                                                                                              +1
                                                                                                              Ну давайте, поищите пейпер, который потверждает ваши слова.
                                                                                                              А то пока тот, что вы привели, их опровергает.
                                                                                                              Найдете — будет 1-1. А я пока подожду :D

                                                                                                              Что несколько не то, что я сказал.
                                                                                                              Давайте честно. Это прямо противоречит тому, что вы сказали. Эпитет «несколько» тут неуместен.

                                                                                                              Насчёт 78% — тут даже цитата в блог посте есть:
                                                                                                              Similarly, most programmers ignore Java's carefully thought out exception hierarchy and simply catch Exception (78%) or Throwable (84%) rather than any of their subclasses.
                                                                                                              Раз уж привели статью, то ссылайтесь на нее, а не какой-то левоватый блог. Да и что это за проценты такие? 100% — это что? 78% от чего? 78%+84% — это как?

                                                                                                              Вот вам цитата из статьи
                                                                                                              Exception is a full 26% of all exceptions
                                                                                                              Далее, в статье, приводятся предположения, почему так происходит. Почитайте таки статью, на которую ссылаетесь, почитайте.
                                                                                                                –2
                                                                                                                Раз уж привели статью, то ссылайтесь на нее, а не какой-то левоватый блог.


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

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

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

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

                                                                                                                    Вы что-то слишком быстро сделали выводы, не прочитав первый пейпер. Но вы же умеете признавать ошибки, верно?
                                                                                                                      0
                                                                                                                      Разные статьи, может быть, тогда признаю ошибку ;)

                                                                                                                      Но числа то все равно совершенно левые. 78% от чего? 84% от чего? От общего количества всех try блоков? Полный бред :)

                                                                                                                      Вероятно это проценты от количества программистов. Т.е. мол 78% из некоего множества инженеров нет-нет да и написали разок `catch (Exception e)`. Ну, такое вполне можне быть.

                                                                                                                      Хотя все равно очень и очень подозрительно, что число у Throwable больше (не все начинающие джависты про него даже знают, кхекхе). Т.е. все равно выглядит как ерунда. Ну либо выборка инженеров была очень уж своеобразная (набрали где-то говнокодеров).

                                                                                                                      По вашему второму пейперу видно, что отлавливают `Throwable` в несколько (раз так в 6-7) реже, чем `Exception`. Откуда берутся 78% и 84% полная загадка.
                                                                                                                        0
                                                                                                                        Так я и написал, что в пейпере несколько не то, что я изначально сказал, и написал, что хочу найти пейпер, чтобы перечитать опять, и понять точно, что это за цифры. И мы мусолим эту тему уже три часа. )
                                                                                                                          0
                                                                                                                          Так я и написал, что в пейпере несколько не то, что я изначально сказал
                                                                                                                          Повторюсь, «несколько не то» тут неуместно :D

                                                                                                                          Вот вам ссылочка на вашу статью. За 5 минут нашлась :)
                                                                                                                          www.computer.org/csdl/proceedings/msr/2016/4186/00/07832935.pdf

                                                                                                                          А вот откуда получились странные числа.
                                                                                                                          To learn more, the number of methods that contained only Exception and Throwable handlers was analyzed further. A staggering 78% of the methods that caught Exception did not catch any of its subclasses and a similar observation of 84% was made for Throwable.
                                                                                                                          Как видно, никакой связи с вашим начальным утверждением :)

                                                                                                                          Кратко же выводы этого пейпера — в Java очень часто тупо ловят Exception, не заморачиваясь с отловом конкретных подклассов. А еще часто перебрасывают его в виде `RuntimeException` (что я уже раньше говорил). В общем не юзают механизм checked exceptions, предпочитая иметь дело с runtime. Что как-бы и не секрет :)

                                                                                                                          Короче, спасибо, вы привели аж 2 пейпера, которые показывают вашу неправоту. Приятно вести дела с таким собеседником!
                                                                                                  +2
                                                                                                  Проблема в том, что нет информации, какая функция вернет ошибку прямо в call site. Для этого нужно лезть в прототип функции. Так что эта проблема исключений свойственна им по определению и все современные языки предлагают этому решение.
                                                                                                    0

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


                                                                                                    Если я правильно понимаю, что вы имеете ввиду под call site, то java дает вам информацию, какая функция какие типы ошибок может вернуть. Все остальное в руках разработчиков, которые этим управляют.


                                                                                                    Ну а так да, это одна из фич джавы, которая почему-то не очень нравится людям.

                                                                                                      0
                                                                                                      Ну и какую информацию здесь мне дает Java?
                                                                                                      void Foo() throws Exception {
                                                                                                          foo.bar1();
                                                                                                          foo.bar2();
                                                                                                      }
                                                                                                      


                                                                                                      И это у Java описаны исключения, а у других это только в документации вроде C# и C++.
                                                                                                        0
                                                                                                        Тут никакую, а если воспользоваться ide, то подсказка по функция вполне помогает.

                                                                                                        Ну, как я уже писал, это вопрос реализации.
                                                                                                          +1
                                                                                                          если воспользоваться ide

                                                                                                          Вот именно. Нужна ide, которая это умеет, но это не главное. Главное, что тратится драгоценное время на чтение кода. Это Go и не хочет повторять. К тому же, это не единственная проблема, которая заставила отказаться от исключений.
                                                                                                            +1

                                                                                                            Почитайте код написанный на go на github, хотя бы раз. После того, как вы перероете все 20 файлов в папке в поисках структуры Config вы поймете, что в go ситуация с "мне нужна ide" еще хуже.


                                                                                                            Это не то, что бы плохо, но вот это "не хочет повторять" не соблюдается.

                                                                                                              –1
                                                                                                              Рыть ничего не нужно. Есть Godoc.
                                                                                                                0

                                                                                                                То есть вам все равно нужно что-то стороннее, что бы смотреть код. Ну и где "не хочет повторять ситуацию"? Просто страничка в браузере, вместо ide, но это не очень помогает.

                                                                                                                  0
                                                                                                                  Сами сменили тему и теперь пытаетесь свою правоту доказать этим. Мне не нужно что-то сторонее, потому что best practices привили обрабатывать всегда ошибку. Поэтому я читаю код, и он намного более ясный, чем код с исключениями. Я вижу по call site, где и когда поток исполнения может изменить свое направление, потому что есть явный return. Это то, что хотела команда Go, отказавшись от исключений, и они своего добились. Сейчас проблема стоит совершенно другая — best practices привели к тому, что код наводнен обработкой ошибок. Этот код надо бы как-то сократить, не утратив все преимущества полученные. Это и есть задача Go 2.

                                                                                                                  Перечитайте с самого начала, в чем изначально проблема Java и исключений в целом. Не в документации, а в том, что call site ничего не говорит. Этой проблемы в Go нет.
                                                                                                                    0

                                                                                                                    Я не вижу проблемы в том, что "call site" не говорит о том, что может возникнуть ошибка в языке, где исключение может возникнуть при любом вызове. Это надуманная проблема.

                                                                                                                      –1
                                                                                                                      А множество других видит, поэтому в Go, Swift, Rust пошли другим путем.

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

                                                                                                                      Это и есть проблема, язык таким быть не должен. Вот `Length` у массива может мне вернуть исключение? Я не знаю, может быть, это же язык, где при любом вызове может быть исключение. В документации не написано, а я ведь умный программист. Поставлю ка я лучше try/catch и в лог это плюну. Это и есть проблема, которая наводнила все exception языки. И checked exceptions в Java ничем ее не решили, как показала практика реального использования, а не фантазий, как теперь все хорошо станет.
                                                                                                                        +1
                                                                                                                        А множество других видит

                                                                                                                        Апелляция к толпе.


                                                                                                                        язык таким быть не должен

                                                                                                                        Почему?


                                                                                                                        Вот Length у массива может мне вернуть исключение?

                                                                                                                        Может. Более того, это может оказаться и не массив благодаря полиморфизму.


                                                                                                                        Поставлю ка я лучше try/catch и в лог это плюну.

                                                                                                                        Если вам надо продолжать работу не смотря на ошибку при попытке получить длину массива, то так и надо делать. Но обычно такой try-catch находится выше по стеку вызовов и накрывает не одно только обращение к Length.


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

                                                                                                                        Проблема-то в чём?

                                                                                                                          0
                                                                                                                          Апелляция к толпе.

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

                                                                                                                          Почему?

                                                                                                                          Потому же, почему критикуют исключения. Если вам неизвестны их недостатки, то вперед в гугл. Информации навалом.

                                                                                                                          Проблема-то в чём?

                                                                                                                          В не очевидности control flow, сложности чтения кода, привитию дурных практики программирования с оборачиванием всего подряд в try/catch. Такое ощущение, что вы только сегодня родились. Проблемы исключений известны настолько же долго, насколько они существуют в языках.
                                                                                                                            0
                                                                                                                            Как любят некоторых вставлять эти заученные фразочки с вики. Нет, это апелляция к насущности проблемы, что аж 3 языка независимо друг от друга предложили все свои решения. Я думаю, что это далеко не все, но из современных эти три сейчас на слуху у всех. Не было бы проблемы не было бы изобретения заново механизмов ошибок.

                                                                                                                            Добро пожаловать в реальный мир. Асинхронное программирование было известно с еще с 80-х или 90-х, но у нас тут тот же nodejs развирусился на фоне "ОООО, асинхронное программирование".


                                                                                                                            Переход на ошибки просто повторяет цикл с 80-х, когда исключений еще не было.


                                                                                                                            В не очевидности control flow, сложности чтения кода, привитию дурных практики программирования с оборачиванием всего подряд в try/catch. Такое ощущение, что вы только сегодня родились. Проблемы исключений известны настолько же долго, насколько они существуют в языках.

                                                                                                                            не очевидности control flow — у вас все еще есть runtime ошибки (panic или что там в других языка), которые могут возникнуть где угодно. Про control flow это скорее rust, который пытается гарантировать правильность работы системы вне unsafe блоков.
                                                                                                                            сложности чтения кода — А как это связано с исключениями?
                                                                                                                            привитию дурных практики программирования с оборачиванием всего подряд в try/catch — Сами по себе исключение этого не делают. Это делают ленивые программисты, или программисты у которых нет время правильно обработать эти исключения. В случае с ошибками они могут их игнорировать, пробрасывать наверх или просто писать в лог и завершать программу. С этой точки зрения ничего не меняется.

                                                                                                                              0
                                                                                                                              Как любят некоторых вставлять эти заученные фразочки с вики.

                                                                                                                              Ох уж эти любители называть вещи своими именами.


                                                                                                                              Нет, это апелляция к насущности проблемы, что аж 3 языка независимо друг от друга предложили все свои решения.

                                                                                                                              NIH


                                                                                                                              Если вам неизвестны их недостатки, то вперед в гугл.

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


                                                                                                                              Впрочем, недостатки мне известны, и Go их никоим образом не решает.


                                                                                                                              не очевидности control flow

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


                                                                                                                              сложности чтения кода

                                                                                                                              Подкрепите ваши слова примерами.


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


                                                                                                                              привитию дурных практики программирования

                                                                                                                              А кто решает какие практики дурные? Вы? Гугл?


                                                                                                                              с оборачиванием всего подряд в try/catch

                                                                                                                              Где вы такое увидели? Сколько я повидал исходников за 20 лет, нигде такого не видел.

                                                                                                                        +1
                                                                                                                        Ну давайте на секунду представим некий гипотетический язык, где
                                                                                                                        1) есть исключения
                                                                                                                        2) любая функия/метод, которые могут кинуть исключение, должны в конце имени иметь "!" (проверяется компилятором). Примерно как публичные методы в Go должны начинаться с заглавной.

                                                                                                                        И тогда ваш пример будет выглядеть так:
                                                                                                                        func Foo!() {
                                                                                                                            foo.bar1!()
                                                                                                                            foo.bar2!()
                                                                                                                        }

                                                                                                                        Вместо
                                                                                                                        func Foo() error {
                                                                                                                            check foo.bar1()
                                                                                                                            check foo.bar2()
                                                                                                                        }

                                                                                                                        Или
                                                                                                                        func Foo() error {
                                                                                                                            if err := foo.bar1(); err != nil {
                                                                                                                                return err
                                                                                                                            }
                                                                                                                            if err := foo.bar2(); err != nil {
                                                                                                                                return err
                                                                                                                            }
                                                                                                                        }


                                                                                                                        Все явно, call-site знает где может быть ошибка. Код не будет наводнен кучей бесползных проверок. Сразу видно, где exit-points у функции.

                                                                                                                        Я никого не призываю внедрять такой подход в Go.
                                                                                                                        Но сами по себе «исключения» не обязательно делают код «менее читабельным». Вопрос именно в реализации.
                                                                                                                          0
                                                                                                                          func Foo!() {
                                                                                                                          foo.bar1!()
                                                                                                                          foo.bar2!()
                                                                                                                          }


                                                                                                                          Я только со второго раза увидел там!.. Думаю в Go таких односимвольных синтаксических элементов избегают не просто так.
                                                                                                                            +1
                                                                                                                            Ну вот опять идут придирки к конкретной реализации :)

                                                                                                                            Причем «субъективные» придирки "я не увидел". Не знаю, может вам не хватат подсветки синтаксиса (я бы такие методы у себя жирным подсвечивал). Может вы читали так много кода на Go, так бегло, что мозг уже игнорирует вещи, которых быть не должно. А может у вас плохой монитор. А может стоит проверить зрение. Много вариантов.

                                                                                                                            В любом случае, я не предлагал/ю внедрять такое в Go.

                                                                                                                            Да… можно было бы думать, если бы язык только разрабатывался…
                                                                                                                            Но сейчас уже, конечно, поздно пить боржоми :D

                                                                                                                            Я лишь хотел показать, что наличие исключений не обязательно означает
                                                                                                                            Проблема в том, что нет информации, какая функция вернет ошибку прямо в call site.
                                                                                                                              0
                                                                                                                              А может у вас плохой монитор.

                                                                                                                              LG 38 inch ultra-wide, рекомендую, кстати, люто.

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

                                                                                                                              В черовниках обсуждается вариант использования `?` вместо `check` и он не кажется удачным. Исключения, опять же, имеют и другие проблемы помимо неявности (stack unwinding, неочевидность того, какой код будет исполнен при ошибке и т.д).
                                                                                                                                0
                                                                                                                                LG 38 inch ultra-wide, рекомендую, кстати, люто.
                                                                                                                                Ну значит проблема не в мониторе. Вычеркиваем из списка…

                                                                                                                                Исключения, опять же, имеют и другие проблемы помимо неявности (stack unwinding, неочевидность того, какой код будет исполнен при ошибке и т.д).
                                                                                                                                Имеют, не имеют… Я не собираюсь обсуждать это в текущей ветке.

                                                                                                                                Тут утверждалось, что с исключениями «нет информации, какая функция вернет ошибку прямо в call site». Это не обязательно не так. Зависит от того, как сделать язык.

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

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

                                                                                                                                  0
                                                                                                                                  То что вы привели в пример – это не исключения. Фраза «от реализации зависит» не делает это исключеним тоже. Так что сорри, пример мимо.
                                                                                                                                    0
                                                                                                                                    А почему это не исключения?

                                                                                                                                    Или если мы вводим в язык строгий гайдлан «любая функция, которая может кинуть исключение, должна в имени содержать такойто суффикс», то это уже не исключения?
                                                                                                                                      0
                                                                                                                                      Ну, вы привели очень короткий пример синтаксической конструкции (опустив остальные элементы, присущие обработке ошибок с помощью исключений) и этим аргументируете о читабельности последних. И это как-то не лепится. Сам по себе приведённый синтаксис вообще ортагонелен исключениям – точно такой же синтаксис может быть у функции, возвращающий явные ошибки.
                                                                                                                                        0
                                                                                                                                        и этим аргументируете о читабельности последних.
                                                                                                                                        Не придумывайте за меня того, чего я не говорил :)

                                                                                                                                        Повторю специально для ВАС
                                                                                                                                        Тут утверждалось, что с исключениями «нет информации, какая функция вернет ошибку прямо в call site». Это не обязательно так. Зависит от того, как сделать язык.
                                                                                                                                          0
                                                                                                                                          и этим аргументируете о читабельности последних.

                                                                                                                                          Не придумывайте за меня того, чего я не говорил :)

                                                                                                                                          Ваша же цитата:

                                                                                                                                          Но сами по себе «исключения» не обязательно делают код «менее читабельным».
                                                                                                                                            0
                                                                                                                                            Хах. Подловили :)

                                                                                                                                            Правда я говорил «не обязательно делают менее читабельным», а не «делают код более читабельным» (как приписываете вы). Но я все же поправлюсь:

                                                                                                                                            Но сами по себе «исключения» не обязательно означают, что нельзя напрямую из кода узнать, какая функция вернет ошибку прямо в call site. Вопрос именно в реализации.

                                                                                                                                            Такая формулировка лучше? :)
                                                                                                                                              0
                                                                                                                                              Лучше, но я не встречал такой реализации. Видимо, этому есть причина.
                                                                                                                                                0
                                                                                                                                                Лучше, но я не встречал такой реализации. Видимо, этому есть причина.
                                                                                                                                                Ну конечно есть! Причина — вся эта «проблема» надуманна и высосана из пальца. В чем, собственно, тут вас (на пару с creker) и пытаются убедить. :D
                                                                                                                                        0
                                                                                                                                        А, я кажется понял.

                                                                                                                                        Вы не прочитали мой изначальный комментарий, только увидели код. Ну и подумали что это я предлагаю заменить `check` на `!`. Нет, не предлагаю. Прочитайте мой комментарий :)
                                                                                                                                          –1
                                                                                                                                          Нет, я его и прочёл. Просто давно потерял нить того, с кем/чем (и зачем) вы спорите и что пытаетесь доказать :)
                                                                                                                              0
                                                                                                                              И внезапно мы получаем ошибки из Swift. Это замечательное решение, но уже исключениями оно не является, т.к. сейчас исключения означают вполне конкретную реализацию, которая универсальна для всех языков.
                                                                                                                                0

                                                                                                                                .

                                                                                                                                  0
                                                                                                                                  Это замечательное решение, но уже исключениями оно не является, т.к. сейчас исключения означают вполне конкретную реализацию, которая универсальна для всех языков.
                                                                                                                                  Подождите, подождите. Т.е. заставить в имя функции добавить некий суффикс в конец если она может кинуть исключение — это уже не исключения? Ну допустим…

                                                                                                                                  А что же тогда такое `Exception` в Java. На всякий случай напомню, что если метод может выкинуть Exception, то он обязан явно содержать `throws Exception` в своей сигнатуре. Как по вашему, это исключения? Это вписывается в ваше определение "сейчас исключения означают вполне конкретную реализацию, которая универсальна для всех языков"?

                                                                                                                                  Судя по вашим предыдущим репликам вы считаете что в Java это таки исключения. Тогда поясните свою позицию пожалуйста, чем принципиально отличается мой теоретический язык от подхода Java?
                                                                                                                                    0
                                                                                                                                    Как по вашему, это исключения?
                                                                                                                                    Нет, так как метод может содержать `throws Exception` в своей сигнатуре, но не выкинуть Exception.
                                                                                                                                      0
                                                                                                                                      Нет, так как метод может содержать `throws Exception` в своей сигнатуре, но не выкинуть Exception.
                                                                                                                                      Т.е. если я напишу `throw new Exception(«bla»)` в Java, то это не исключения?

                                                                                                                                      А если напишу `throw error.New(«bla»)` в моем гипотетическом языке, это исключения?
                                                                                                                                        0
                                                                                                                                        Т.е. если я напишу `throw new Exception(«bla»)` в Java, то это не исключения?
                                                                                                                                        Я вроде о сигнатуре метода написал
                                                                                                                                          –1
                                                                                                                                          Я не знаю о чем вы пишете.

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

                                                                                                                                          А в моем «гипотетическом языке» это уже, внезапно, не исключения. Хотя суть та же — если кидаем исключение, то нужно пометить сигнатуру. Если нет — все еще можно пометить сигнатуру.

                                                                                                                                          Может быть вы наконец поясните эту непонятную для меня позицию?
                                                                                                                                            0
                                                                                                                                            Хотя в Java и нужно помечать сигнатуру метода специальным образом.
                                                                                                                                            В Java не всегда надо помечать сигнатуру метода специальным образом
                                                                                                                                              0
                                                                                                                                              В Java не всегда надо помечать сигнатуру метода специальным образом
                                                                                                                                              Т.е. если бы нужно было помечать всегда (не было бы RuntimeException), то в Java бы не стало бы исключений вовсе?

                                                                                                                                              Так что, получается `throw new RuntimeException()` — это выброс исключения. А `throw new Exception()` — это что тогда?
                                                                                                                                                0
                                                                                                                                                А `throw new Exception()` — это что тогда?
                                                                                                                                                Это механизм заставить проверить на один уровень выше, как в Go
                                                                                                                                                  –1
                                                                                                                                                  Это механизм заставить проверить на один уровень выше, как в Go
                                                                                                                                                  «Механизм» это когда в сигнатуре есть `throws Exception`. А тут именно `throw new Exception(). Что это такое?
                                                                                                                                                  подсказка
                                                                                                                                                  выброс исключения
                                                                                                                                                    0
                                                                                                                                                    Что это такое?
                                                                                                                                                    Legacy