DEV Community

Cover image for Attempting to Learn Go - Let's Get Modular - Again!
Steve Layton
Steve Layton

Posted on

Attempting to Learn Go - Let's Get Modular - Again!

Let's Get Modular - Again

Previously, we released our very first module version of the mailgunner package. This time around let's see what we would need to do to release a new version - we'll make a few small tweaks to the code, update the readme, and then cut a new release.

Ditch http.DefaultClient, Sort of

One of the issues with using http.DefaultClient is that it doesn't set some sensible defaults, it's basically, just like it says, a barebones client. What if someone needs to proxy a request? Or set a timeout? It can't be done easily with our previous module. Since that's the case, we want to make it so our module isn't reliant on it. So we're going to extend it a bit to make it possible to pass in a custom client. We're really own changing the New() function so, I'll only show that here, refer to the repo or the previous article to see the complete code.

Our original function was very simple, just returning a struct that contained two strings and http.DefaultClient.

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

func New(apiurl, apikey string) MgClient {
  return MgClient{

As I said we won't be changing the struct itself - we'll simply update New() to take another parameter. Also, note that we're now returning a pointer to the MgClient which probably should have been in the previous version. But hey, we're still learning. Our new parameter, cleverly named, client will accept *http.Client - we'll go over how to actually use it in a bit.

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

If whoever is using the module declines to create a custom client and passes nil instead we'll fall back to using http.DefaultClient.

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

Custom Client

Alright, but how do we make use of the custom client? It's actually pretty easy! Before calling New() we'll make a new variable named cc and give it &http.Client{} with a timeout of 10 seconds.

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

With our fancy custom client in hand, we'll pass that into New() as our shiny new third parameter.

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

Everything else works as it did before. πŸŽ‰

Lets Go v2

We're not quite ready to release our new module, first, we'll have to update the readme, which I won't repost here for brevity. Afterward, we then need to update our go.mod file to indicate we're at a new version. I've decided this is a major version since we've changed the signature of the New() function. The new go.mod simply has "v2" appended to it.


We'll run through our Git commands to push everything to Github. We'll start by making a v2 branch (which you likely would create before you started making code changes, I didn't happen to though), adding our changes, which are then committed to that branch.

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"

So far so good. Now we'll push our branch up to the remote, then tag and push the tags.

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

Now anyone can simply import the module with a /v2 and run go build to be in business!

➜  GO111MODULE=on go build -v

GitHub logo shindakun / mailgunner

A super simplistic send only implementation of a Mailgun client in Go.


A super simplistic send only implementation of a Mailgun client in Go.


Use as a module, import, then run

go mod init module
go build

If you are new to modules checkout my post on for some more details.

go get


See example/main.go for a usage example.

Change log

  • Updated New() to take http.Client so we don't have to rely on http.DefaultClient

Next time

I'm still thinking about putting together a series of posts on how I want to build out a "devlog" over on my own domain. I just need to decide how I want to tackle it.

Well, until then...

You can find the code for this and most of the other Attempting to Learn Go posts in the repo on GitHub.

Top comments (0)