Pull to refresh

Comments 5

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

   err := req.ParseForm()
   if err != nil {
      rw.WriteHeader(http.StatusInternalServerError)
      rw.Write([]byte(err.Error()))
      return
   }

Здесь сразу несколько проблем:

  1. Если не удалось распарсить форму, то это не Internal Server Error. Почти во всех (или вообще во всех) случаях ошибки, которые может вернуть ParseForm, возникают из-за недопустимого формата запроса, например как вот тут

  2. Есть отдельный метод http.Error, который намного компактнее позволяет записывать возврат ошибки в HTTP обработчике: https://pkg.go.dev/net/http#Error

  result, err := logic(ctx, data)
   if err != nil {
      rw.WriteHeader(http.StatusInternalServerError)
      rw.Write([]byte(err.Error()))
      return
   }

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

req, err := http.NewRequest(http.MethodGet,
                                        "http://example.com?data="+data, nil)

Данные в запросе должны экранироваться, лучше всего с помощью структуры url.Values и метода Encode()

defer resp.Body.Close()
       if resp.StatusCode != http.StatusOK {
   return "", fmt.Errorf("Unexpected status code %d",
   resp.StatusCode)
   }

Очень распространённая ошибка: тело запроса не вычитывается до конца, если произошла ошибка (не в смысле, что метод .Do() вернул ошибку, а что сервер ответил, но с HTTP кодом отличным от 200. В этом случае (если тело запроса не прочитано) соединение с сервером будет закрыто и keep-alive для соединения не будет работать. Это становится важно, когда запросов к одному и тому же серверу выполняется много: могут даже закончиться исходящие порты на сервере, который отправляет запросы.

err := callServer(ctx, "fast", fastURL+"?error="+errVal)

Аналогично, нет экранирование значения

Самый полезный комментарий из всей статьи)

Go: идиомы и паттерны проектирования

Ожидание: вот книга где наконец-то расскажут как строить архитектуру приложений в Go! Наконец-то смогу узнать как наилучшим образом применять SOLID и GoF в Go!

Реальность: ещё одна книга по основам Go. Зачем, если есть книга Алана Донавана и Брайна Кернигана?

Надеюсь в книге будет описано зачем и почему был выбран такой странный синтаксис обработки исключений?

   data, err := ioutil.ReadAll(resp.Body)
   if err != nil {...

Это не исключения :). Это обработка ошибок с помощью фичи языка под названим «возврат нескольких значений из функции». Поэтому синтаксис кажется странным.

Sign up to leave a comment.