Так выглядит код на языке Go:
func getIDs() (ids []int, err error) { resp, err := http.Get("http://localhost:9874/people/ids") if err != nil { return nil, fmt.Errorf("error fetching ids: %v", err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("error reading response body: %v", err) } err = json.Unmarshal(body, &ids) return }
Обратите внимание, как здесь обрабатываются ошибки:
resp, err := http.Get("http://localhost:9874/people/ids") body, err := ioutil.ReadAll(resp.Body)
В Go не используется try-catch. Вместо этого функция возвращает два значения — результат работы и ошибку (если ошибки нет, ошибка равна null
).
Кстати, похожим образом обрабатываются ошибки в JS при работе с асинхронностью (см. compose-callback).
Пусть у нас есть функции, которые бросают ошибки.
function sum(a, b) { if (typeof a !== "number" || typeof b !== "number") { throw new Error("Invalid arguments"); } return a + b; } function double(x) { if (typeof x !== "number") { throw new Error("Invalid argument"); } return x * 2; }
Как вызвать эти функции безопасно? Например, мы хотим, чтобы функция foo(a, b)
считала (a + b) × 2
, вызывая sum
и double
. Если функции вызываются корректно, foo
возвращает число. Если с ошибками — NaN
.
function foo(a, b) { let s; try { s = sum(1, 2); } catch (e) { return NaN; } try { return double(s); } catch (e) { return NaN; } }
Реализуйте функцию wrap
, которая трансформирует функции так, чтобы они работали в стиле Go.
Функция должна возвращать массив:
null
(обозначат отсутствие ошибки) и результат работы функцииconst wrappedSum = wrap(sum); const wrappedDouble = wrap(double); function foo(a, b) { const [e1, s] = wrappedSum(1, 2); if (e1 !== null) { return NaN; } const [e2, res] = wrappedDouble(s); if (e2 !== null) { return NaN; } return res; }