DEV Community

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

Posted on • Updated on

Attempting to Learn Go - Let's Get Modular!

Let's Get Modular

Remember this?

mkdir $GOTPATH/
mkdir $GOTPATH/

You may not if you didn't read the previous post on sending email through MailGun. It's really sloppy and I only really did it that way to make it a bit easier to use the package locally with a proper example. I didn't like it very much and it still hasn't been posted on GitHub because of it. So, I thought we'd do a quick post covering making mailgunner a proper Go module.

Prep work

The first thing we'll do is create a directory outside of the $GOPATH. You can use modules inside with the GO111MODULE=on environment variable but, since this is all about doing away with $GOPATH we'll work outside of it.

mkdir ~/Code/mailgunner

Now, create a main.go and open it in VS Code.

touch main.go
code .

The code is already written so I just paste it in. Note, that I've updated the package name from client to mailgunner. I've also added simple comments to the exported functions. This gives us some details using Intellisense in VS Code. I should probably make them a bit more useful though.

Intellisense in Action

I'm not going to go through the code again, just providing it here so you do not have to jump to the repo or the previous article. *Note: I made a slight tweak to the code after the fact, and renamed the NewMgClient function to the more correct New().

package mailgunner

import (

// MgClient struct holds our URL and API key
type MgClient struct {
  MgAPIURL string
  MgAPIKey string
  Client   *http.Client

// New returns our MgClient with the proper settings
func New(apiurl, apikey string) MgClient {
  return MgClient{

// FormatEmailRequest puts everything together for sending
func (mgc *MgClient) FormatEmailRequest(from, to, subject, body string) (r *http.Request, err error) {
  data := url.Values{}
  data.Add("from", from)
  data.Add("to", to)
  data.Add("subject", subject)
  data.Add("text", body)

  r, err = http.NewRequest(http.MethodPost, mgc.MgAPIURL+"/messages", strings.NewReader(data.Encode()))
  if err != nil {
    return nil, err
  r.SetBasicAuth("api", mgc.MgAPIKey)
  r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
  return r, nil

To make it a proper module we then need to initialize it.

$ go mod init
go: creating new go.mod: module

Now, let's get our Git repo set up. If you are not familiar with Git I recommend taking some time to check it out. Pro Git is available online for free.

git init
git add .
git commit -m "Initial commit"
git remote add origin
git push -u origin master

Now to make full use of Go modules we'll need to tag our release with a version number. We'll follow Semantic Versioning and tag our release as version 1 or v1.0.0 and push the tag to Github.

git tag v1.0.0
git push --tags

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

Using Modules

Alright, great - but, how do we use it? The Git repo includes an example bit of code. Go ahead and clone the repo into a directory outside your $GOPATH. Navigate to the example directory. Then we'll initialize it to make use of the module. Finally, run go build, it will look something like the following.

$ go mod init example
go: creating new go.mod: module example
$ go build
go: finding v1.0.0
go: downloading v1.0.0

Look, at that - no more using go get!

Next time

I want to take some time to look at web servers in Go so we'll probably look at making simple servers. They may not be production ready but it should still be fun to throw them up on the internet to see them in action. I had some other ideas of silly projects to try and work which I may get to first, we'll see what happens.

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 (2)

jay97 profile image
Jamal Al

Nice read. Simply and easy to understand

shindakun profile image
Steve Layton

Thanks for the comment! Glad you liked it.