Given the changes with Go Modules I wanted to document a brief getting started for Go projects, this will focus on building a minimal web service.
Before you start you will need to install Go, I recommend using homebrew or for ubuntu users Golang Backports, or as last resort grab it from the Go Downloads page.
So this looks like this for OSX.
brew install go
Or for ubuntu we add the PPA, then install golang 1.14 and update our path.
sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt-get update
sudo install golang-1.14
echo 'export PATH=$PATH:/usr/lib/go-1.14/bin' >> ~/.bashrc
source ~/.bashrc
Now we should be able to run.
go version
Now navigate to where you build your projects, for me this is ~/Code/goprojects
and make a folder. One thing to note here is that this goprojects
folder is not in my $GOPATH
as we are using modules.
cd ~/Code/goprojects
mkdir simple-go-service
cd simple-go-service
Before we start adding code lets initiliase our project, you should replace USERNAME with your github username, for me it is wolfeidau.
go mod init github.com/USERNAME/simple-go-service
Now for me I follow a pattern of storing the entry point in a cmd
folder, this is done so I can easily customise the name of the binary as go
uses the parent folder name executables.
mkdir -p cmd/simple-service
touch cmd/simple-service/main.go
Now add some code to the main.go
you created in the previous command, this will listen on port :8000
for web requests.
package main
import (
"io"
"log"
"net/http"
)
func main() {
// Hello world, the web server
helloHandler := func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hello, world!\n")
}
http.HandleFunc("/hello", helloHandler)
log.Println("Listing for requests at http://localhost:8000/hello")
log.Fatal(http.ListenAndServe(":8000", nil))
}
Now run this with the following command.
go run cmd/simple-service/main.go
This should print out a URL you can navigate to in your browser and see the classic Hello, world!
.
Now from here you will want to setup an editor, I personnally use vscode which has really good support for golang once you add the go plugin.
From here I would recommend looking at something like echo which is a great web framework, it is well documented and has lots of great examples.
To add this library either just add the import in your editor, vscode will automatically trigger a download of libraries or run.
go get -u -v github.com/labstack/echo/v4
NOTE: We are using the v4
tagged import as we are using Go Modules, also I have also ensure this v4 tag is in the imports in the following example.
And update the main.go
to use this great little REST crud example.
package main
import (
"net/http"
"strconv"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
type (
user struct {
ID int `json:"id"`
Name string `json:"name"`
}
)
var (
users = map[int]*user{}
seq = 1
)
//----------
// Handlers
//----------
func createUser(c echo.Context) error {
u := &user{
ID: seq,
}
if err := c.Bind(u); err != nil {
return err
}
users[u.ID] = u
seq++
return c.JSON(http.StatusCreated, u)
}
func getUser(c echo.Context) error {
id, _ := strconv.Atoi(c.Param("id"))
return c.JSON(http.StatusOK, users[id])
}
func updateUser(c echo.Context) error {
u := new(user)
if err := c.Bind(u); err != nil {
return err
}
id, _ := strconv.Atoi(c.Param("id"))
users[id].Name = u.Name
return c.JSON(http.StatusOK, users[id])
}
func deleteUser(c echo.Context) error {
id, _ := strconv.Atoi(c.Param("id"))
delete(users, id)
return c.NoContent(http.StatusNoContent)
}
func main() {
e := echo.New()
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.POST("/users", createUser)
e.GET("/users/:id", getUser)
e.PUT("/users/:id", updateUser)
e.DELETE("/users/:id", deleteUser)
// Start server
e.Logger.Fatal(e.Start(":1323"))
}
Now run this with the following command.
go run cmd/simple-service/main.go
Hopefully you have managed to get this service running and started testing it with something like postman ๐.
For next steps I recommend reading How do I Structure my Go Project?.