Golang is simple, efficient and has potential to revolutionize backend processing. It is the optimal language for microservices architecture.
The best way to get started with Golang is to read the official document.
IDEs for Go
I have used Sublime, Atom and Visual Studio and even plain old Emacs for writing Go code. Of all the IDEs, I found Visual Studio ideal for me as a developer learning a new language as well as to quickly navigate through projects built together with my team. For more on using Visual Studio with Go, read the link below.
https://code.visualstudio.com/docs/languages/go
Best Practices
- Prior to all checkins please run gofmt -w yourfile.go (IDEs have plugins that run this for you)
- Packages are given lower case, single-word names; there should be no need for underscores or mixedCaps
- Interface names and variables Convention in Go is to use MixedCaps or mixedCaps rather than underscores to write multiword names
- Only functions / variables starting with a capital letter would be usable outside the package. All other internal functions start with lower case
- Panics should as much as possible not cross package boundaries and if they do it should be made clear in the package documentation.
- There is linter tool https://github.com/golang/lint which recommends “proper” syntax for your programs (cd myProject; golint ./… )
- Other great tools:
- errcheck
- go vet
- go test -race
Programming in Go
Although Go borrows from a lot of languages, it has some characteristics that are either left out or unusually implemented. For the most part it is done to achieve a more simplistic syntax and to write more efficient code. It is important to know these idioms especially for experienced programmers that have written code in other languages.
For a comprehensive detail on the Go language the best resource is the official Golang document.
https://golang.org/doc/effective_go.html
I have listed below a few nuances of the language that stood out to me when developing with Go:
- There is no do or while loop in Go. You can use a generalized for;
- There is no automatic fall through in switch cases in Go.
- We can use break to terminate a switch or loop early. In addition a label can be used to break out of a nested loop. u
- Use defer for closing handles and unlocking mutexes immediately after opening or locking. This will ensure you don’t forget to do so later.
- We can return the address of a local variable created within a function. This can be used outside the function. E.g.
- return &Node{Data: d, Next: nil}
- make is used only for slices, channels and maps
- new is a rarely used in Go. new(T) allocates storage for T and returns its address .
- Go’s arrays and slices are one-dimensional. To create two dimensional arrays or slices, we define it as an array of arrays or a slice of slice of slices. An inner slice can be of different lengths.
- Only interfaces can be embedded within interfaces.
Deployment
Manage Go package dependencies using godep:
https://github.com/tools/godep
Building for Linux on mac
Setup Cross compilation One needs to compile Go compiler for different target platforms and architectures. This is done from src folder in go installation. If you use Homebrew on OS X, then you have a simpler solution, install go with cross compilers:
$ brew install go --with-cc-all
Then to build:
GOOS=linux GOARCH=386 CGO_ENABLED=0 go build -o appname-linux appname.go
Optimize Go binaries in production
These options will help shrink Go binaries sizes by removing some debugging data. Note that panics will still give you info.
-s Omit the symbol table and debug information.
-w Omit the DWARF symbol table.
Go Gotchas
This is a compilation of example that I encountered in Go that either stumped me or I had to find a workaround for. Making a list helps me remember them when I’m coding.
No built-in race condition safety
Go does not restrict access to shared data. A Go programmer has to explicitly synchronize and manages shared resources, else there could be race conditions making for some messy real-time problems.
You can use Go’s race detector to check a race condition in your Go code:
go run -race incrementor.go
Note that the race detector has a limit of 8192 simultaneously alive goroutines. Reduce the number of goroutines in a program if you want to verify it with the race detector.
Date Formatting
Go just doesn’t use an abstract syntax for datetime components (YYYY-MM-DD), but these exact numbers. No other number will do!
These are predefined layouts for use in Time.Format and Time.Parse. The reference time used in the layouts is the specific time: Mon Jan 2 15:04:05 MST 2006 which is Unix time 1136239445.
Since MST is GMT-0700, the reference time can be thought of as 01/02 03:04:05PM ’06 -0700 To define your own format, write down what the reference time would look like formatted your way; see the values of constants like ANSIC, StampMicro or Kitchen for examples.
The model is to demonstrate what the reference time looks like so that the Format and Parse methods can apply the same transformation to a general time value.
Marshal UTF-8 characters to JSON
Marshaling a string like “TV & Home Entertainment”, will generate JSON like
"category": "TV \\u0026 Home Entertainment",
The best way to do this is to disable HTML escaping as follows.
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
enc.Encode(&textToBeMarshalled)
fmt.Println(buf.String())
Maps and struct
Assign a struct field off map has to be done by first creating the element in golang.
type apiNode struct {
method, expectedfile string
}
var handlerMap map[string]apiNode
handlerMap = make(map[string]apiNode)
handlerMap[APIName] = apiNode{"GET","a.json"}
Reference Links
Godoc to the source – https://blog.golang.org/godoc-documenting-go-code