У вас включен AdBlock или иной блокировщик рекламы.

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

Спасибо за понимание.

В другой раз
DevGang блог о програмировании
Авторизоваться

Изучаем Go – Снова о модульном проектировании

Снова создаем модули 

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

Ditch http.DefaultClient, Sort of

Одна из проблем, связанных с использованием http.DefaultClient, заключается в том, что он в основном, как говорится, как клиент barebones, не устанавливает каких-либо разумных значений по умолчанию. Что же делать, если кому-то нужно сделать прокси-запрос? Или установить таймаут? Реализация таких задач с использованием нашего предыдущего модуля перестает быть тривиальной задачей. Именно поэтому нам нужно организовать взаимодействие так, чтобы наш модуль не зависел от этого. Итак, мы собираемся немного расширить его возможности, чтобы мы смогли перейти на собственный клиент. Мы изменили функцию New(), я покажу здесь, что мы именно поменяли, а в репозитории или предыдущей статье, вы сможете увидеть полный код.

Изначально, наша функция была очень простой и просто возвращала структуру, которая содержала две строки и http.DefaultClient.

type MgClient struct {
  MgAPIURL string
  MgAPIKey string
  Client   *http.Client
}

func New(apiurl, apikey string) MgClient {
  return MgClient{
    apiurl,
    apikey,
    http.DefaultClient,
  }
}

Как я говорил, мы не будем изменять саму структуру - мы просто обновим метод New(), чтобы получать другой параметр. Заметьте, теперь мы возвращаем указатель на MgClient, который, вероятно, должен был быть в предыдущей версии. Но мы же пока только тренируемся и учимся). Наш новый параметр, с умным именем, client примет * http.Client - мы еще немного рассмотрим, как нужно правильно его использовать.

func New(apiurl, apikey string, client *http.Client) *MgClient {
  if client == nil {
    client = http.DefaultClient
  }
  return &MgClient{
    apiurl,
    apikey,
    client,
  }
}

Если кто-то используя модуль, отказывается создавать собственный клиент и вместо него передает nil, мы вернемся к использованию http.DefaultClient.

mgc := mailgunner.New(apiurl, mgKey, nil)

Настраиваемый клиент

Итак, как же мы можем использовать наш кастомный клиент? На самом деле довольно легко! Перед вызовом метода New() мы создадим новую переменную cc и передадим ей & http.Client{} со временем ожидания (таймаутом) в 10 секунд.

cc := &http.Client{
    Timeout: time.Second * 10,
  }

Как раз таки это станет блестящим третьем параметром передаваемым нашим необычным клиентом в метод New().

mgc := mailgunner.New(apiurl, mgKey, cc)

Все остальное будет работать совершенно так же как и ранее.

v2 версия

Мы все еще не совсем готовы выпустить новый модуль, т.к, во-первых, нам придется обновить файл readme, который для краткости я не буду здесь указывать. Затем нам нужно обновить файл go.mod, чтобы указать, что мы переходим к новой версии. С того момента, как мы изменили сигнатуру функции New(), я решил, что это будет наша основная версия, а новый go.mod просто добавил "v2" к ней.

module github.com/shindakun/mailgunner/v2

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

git checkout -b v2
git add .
git commit -m "Updated New() to take http.Client so we don't have to rely on http.DefaultClient"

Все идет по плану, а теперь мы перенесем нашу ветку в remote, затем отметим и вставим метки (tags).

git push --set-upstream origin v2
git tag v2.0.0
git push --tags origin v2

Теперь любой желающий может просто импортировать модуль с помощью /v2, запустить go build и с удовольствием работать!

➜  GO111MODULE=on go build -v
github.com/shindakun/mailgunner/v2
github.com/shindakun/mailgunner/v2/example

В продолжении

Я все еще думаю о том, чтобы сделать серию постов о создание «devlog» на своем собственном домене. Мне еще нужно решить, как именно это сделать.

До скорого ...

Другие статьи из цикла:

#Golang