To install go through homebrew (or to update it to the latest version), run:
brew update
brew install go # if go is not yet installed - and/or -
brew upgrade go # update an existing go installation
Check that you have the latest version:
go version
You'll need to create a local directory that will be used as the 'Go Workspace'. This workspace will be shared between all of your projects, so generally you'll need only one.
For example:
mkdir ~/go
Then setup these environment variables, ideally in your ~/.bashrc
file.
export GOPATH=$HOME/go
export GOROOT=/usr/local/opt/go/libexec
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
Install the go-plus plugin. On startup, it will do some sanity checks to make sure everything is set up correctly. In case of errors, double check that you've set up your environment variables correctly in the current (atom) session. To make sure, start a new bash session, and run atom from there.
This plugin will:
Go is pretty opinionated about where it wants your code to be located.
Your code is expected to be stored in
$GOPATH/src/github.com/your-username/your-projectname
.
The idea is that any project/package you write is easily shareable.
Instead of the github.com
format, there are a few others like bitbucket, mercurial, etc (Read more about Package Publishing)
mkdir -p $GOPATH/src/github.com/your-username
mkdir $GOPATH/src/github.com/your-username/your-projectname
Start with a simple file, for example:
package main
import (
"flag"
"fmt"
)
var greetingFlag string
func init() {
flag.StringVar(&greetingFlag, "greeting", "Hello", "Type of greeting")
}
func main() {
flag.Parse()
fmt.Println(fmt.Sprintf("%s, go!", greetingFlag))
}
Build your application like this:
go build
You can now run your built executable:
./go-test -greeting="What's up"
With some small updates, you can turn your console application into a web application:
package main
import (
"flag"
"fmt"
"net/http"
)
var greetingFlag string
func init() {
flag.StringVar(&greetingFlag, "greeting", "Hello", "Type of greeting")
}
func main() {
flag.Parse()
fmt.Println(fmt.Sprintf("%s, go!!", greetingFlag))
http.HandleFunc("/", hello)
http.ListenAndServe(":8080", nil)
}
func hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf("%s, go!!", greetingFlag)))
}
The $GOPATH design is a bit weird when coming from package managed languages like php/composer, nodejs/npm, etc. In Go 1.5 there is a development experiment to support a vendor/
directory, like these other package managers.
Read more about it here. It is based on Glide
To use it, you'll need to set the environment variable GO15VENDOREXPERIMENT
to 1
and install glide
:
export GO15VENDOREXPERIMENT=1
brew install glide
In your project directory, use glide like this:
glide create # creates your glide.yaml if it does not exist
Now edit your newly created glide.yaml
file to list your dependencies, for example:
package: main
# Declare your project's dependencies.
import:
- package: github.com/Masterminds/cookoo
repo: git@github.com:Masterminds/cookoo.git
ref: 1.1.0
vcs: git
Note how you can specify repository locations, and most importantly: explicit versions.
Now install these dependencies in vendor/
with the following command:
glide install
you can build your package as usual:
go build
Because of the environment flag, it will try to locate your dependencies in the vendor/
directory.
Most recommendations so far suggest to simply output data using fmt.Printf
. As Go is making heavy usage of struct
, you'll often want to output all fields of a struct. A simple way to do this:
fmt.Printf("%+v\n", someData)
You could use a nice logger like logrus for logging messages, augmented with custom fields.
Import it like this:
import log "github.com/Sirupsen/logrus"
Then log a message like this:
log.WithFields(log.Fields{
"animal": "walrus",
}).Info("A walrus appears")
You can tweak the logrus settings in init:
func init() {
// Log as JSON instead of the default ASCII formatter.
log.SetFormatter(&log.JSONFormatter{})
// Output to stderr instead of stdout, could also be a file.
log.SetOutput(os.Stderr)
// Only log the warning severity or above.
log.SetLevel(log.WarnLevel)
}
For lower level debugging you can use Mailgun's godebug
Install godebug:
go get github.com/mailgun/godebug
Then add breakpoints to your code like this:
_ = "breakpoint"
To run your app, simply:
godebug run hello.go
Your app will run normally, until it hits the breakpoint. There you can use a few basic commands to list context, and print variables (including structs) in their current state.
Think of this as Go's equivelant of var_dump. Add it to your imports like this:
import spew "github.com/davecgh/go-spew/spew"
Then whatever variable (including structs) you want to output, simply use:
spew.Dump(v) // output to console directly
fmt.Printf(spew.Sdump(v)) // create a string
When working on web-apps and servers, you generally don't want to manually recompile and restart your app every time you change a line of code. This is where reloading comes in.
On Mac OS X you will get a popup from the firewall, asking if your newly built app is allowed to open incoming connections. It does this every time your app changes (new binary file content hash). This is obviously very annoying during development. To solve it, always make sure that your web app is listening to the local host ip (127.0.0.1) only, and not any public or catch-all addresses.
The gin app is a simple proxy server that rebuilds your app when .go files changes, and restarts a server.
Install it using go get github.com/codegangsta/gin
, and use gin -h
to read about the options. In general, this is all you need to get started:
gin -a "8080" run
Now you can simply open up this url in your browser to view your app: http://127.0.0.1:3000
(note: not the port specified with -a!)
Gin will monitor the current directory for changes. If a .go file is changed, a go run
is executed, and the app is stopped/started. The proxy is forwarding requests to port 3001 by default, which you can override with -a
.
Note that this is a very ungraceful restart only suitable for development. In production you'll need to work with loadbalancers.
Here's a blog post about reloading code through gulp. That would require mixing node in the project, so gin
would be a cleaner solution.
Copyright © Joost Faassen 2010-2022