Thursday, 21 March 2019

Golang - Miscellaneous Topics & Useful Links

Go CLI commands

go get

-u is used frequently as it makes get not just to check out missing packages but also to look for updates to existing packages 

Coding Style


https://github.com/golang/go/wiki/CodeReviewComments
https://github.com/Unknwon/go-code-convention/blob/master/en-US/naming_rules.md
https://rakyll.org/style-packages/
Golang - Code organisation with structs, variables and interfaces
Special Packages and Directories in Go

Go naming conventions for const
The standard library uses camel-case, so I advise you do that as well. The first letter is uppercase or lowercase depending on whether you want to export the constant.

Inner/package functions should not be calling panic on error but should return an error (together with a value) and thus allow caller to decide how they want to handle errors and if they want to panic or not.

Function should detect an error and return as soon as possible. The last statement in function body should be returning a valid value and nil as an error.

How to organize Go project?


Go Project Layout
golang-standards/project-layout

How to order packages in import?


Keep them in alphabetical order, with a blank line between:

  • the standard library
  • other libraries 
  • project-specific imports

gofmt: organize imports like eclipse does

Initialization


init functions in Go


Error Handling


Error handling and Go
Custom Errors
Return nil or custom error in Go
When should I use panic vs log.fatalln() in golang?
Part 32: Panic and Recover
Go by Example: Panic

    if err != nil {
        panic(err)
    }

Constants


https://blog.golang.org/constants
Constants in Go established during init

Types


integers



Strings


Printing " (double quote) in GoLang
Use:
  • escape character: fmt.Println("\"") or
  • raw strings: fmt.Println(`"`)
Go by Example: Number Parsing

Enums


Ultimate Visual Guide to Go Enums
Command stringer
Simple enumeration in Golang using Stringer
Assign a string representation to an enum/const (forum thread)
[Golang] Enum and String Representation
Enums in Go

Structs


Go by Example: Structs
Anonymous fields in structs - like object composition
The empty struct

Return pointer to local struct
Go performs pointer escape analysis. If the pointer escapes the local function, the object is allocated on the heap. If it doesn't escape the local function, the compiler is free to allocate it on the stack.

Note that, unlike in C, it's perfectly OK to return the address of a local variable; the storage associated with the variable survives after the function returns.[1]

When possible, the Go compilers will allocate variables that are local to a function in that function’s stack frame. However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors.[1]

Can you “pin” an object in memory with Go?
An object on which you keep a reference won't move. There is no handle or indirection, and the address you get is permanent. Go's GC is not a compacting GC. It will never move live objects around.

Local variable can escape the local function scope in two cases:
  • variable’s address is returned
  • its address is assigned to a variable in an outer scope


When to return a local instance of struct and when its address?


There are two usual reasons to return a pointer:

  • if we want methods of the struct to generally modify the struct in place (versus needing to create or copy to a new struct when we want to make modifications)
  • if the struct is rather large, a pointer is preferred for efficiency


When to return a pointer?
Constructor returning a pointer

Immutability


Does Go have immutable data structures?

Arrays


GO explicit array initialization
Keyed items in golang array initialization

Slices


https://golang.org/ref/spec#Slices
https://gobyexample.com/slices
https://blog.golang.org/go-slices-usage-and-internals

Channels


Unbuffered 


Example in SO quuestion

Buffered 


A Tour of Go - Channels 
BUFFERED CHANNELS IN GO: TIPS & TRICKS
Buffered Channels In Go — What Are They Good For?
Buffered Channels
Go by Example: Channel Buffering
Different ways to pass channels as arguments in function in go (golang)
https://www.reddit.com/r/golang/comments/7ep1un/golang_channel_is_really_fifo/

Interfaces


Interfaces in Go


Control Flow


for / range


Is there a way to iterate over a range of integers in Golang?
for range [5]int{} {...}

Switch

https://gobyexample.com/switch
https://tour.golang.org/flowcontrol/9
https://github.com/golang/go/wiki/Switch
https://yourbasic.org/golang/switch-statement/


defer

A Tour of Go - defer

panic


When should I use panic vs log.fatalln() in golang?


Functions


Go function type, reusable function signatures
type myFunctionType = func(a, b string) string

Arguments


Verifying arguments



Methods


Methods on structs
You will be able to add methods for a type only if the type is defined in the same package.
Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang
Anatomy of methods in Go

Lambdas inside a function

Why doesn't Go allow nested function declarations (functions inside functions)?

OOP - Encapsulation & import


Exported identifiers in Go
What does an underscore in front of an import statement mean in Golang?

dot-import

When you import package prefixed with dot (e.g.: import( . "fmt")), it would be imported in current namespace, so you can omit "fmt" prefix before calling methods. BUT: Don't ever do that; the only time it's useful is in very rare cases involving test files, everywhere else it's a really bad idea.

Concurrency


Go Concurrency Patterns: Pipelines and cancellation
Go Language Patterns - Semaphores
Go’s Extended Concurrency: Semaphores (Part 1)
Essential Go - Limiting concurrency with a semaphore

Unit & Integration Testing



First, something not related specifically to Go but to general software engineering:
TDD and BDD Differences"BDD is just TDD with different words"
Why do some software development companies prefer to use TDD instead of BDD?
How can I do test setup using the testing package in Go
Nice example how to inject unit test checker in an internal method: compare Do() and do() here.
Verbose output prints the names of unit test functions: go test -v
Exploring the landscape of Go testing frameworks
Go With Go(Lang): Features and Testing Frameworks

BDD:
  • ginkgo [Ginkgo] - very active development
  • goconvey
  • goblin - seems that its development has stopped; the last commit in repo was 5 months ago

5 simple tips and tricks for writing unit tests in #golang
Integration Tests in Go
Integration Test With Database in Golang
Separating unit tests and integration tests in Go
Learn Go by writing tests: Structs, methods, interfaces & table driven tests
Testing with golden files in Go
BDD Testing with Ginkgo and GoMock
Clean Go Testing with Ginkgo
done channel 
Using Ginkgo with Gomock
golang/mock
Gomega
Filesystem impact testing
Testing Techniques - Google I/O 2014

Go & DataBases


Scanners and Valuers with Go
How to write unit tests for database calls

Design Patterns in Go


The factory method pattern in Go
Factory patterns in Go (Golang)
A Class Factory in Golang (Google Go)

Go in VSCode

Debugging Go code using VS Code

Misc



Things I Wish Someone Had Told Me About Golang

Random


Package rand
Generating random numbers and strings in Go
https://flaviocopes.com/go-random/
Go by Example: Random Numbers
package uuid

Environment Variables

Pass environment variables from docker to my GoLang.

Configuration Files


Best practices for Configuration file in your code
Manage config in Golang to get variables from file and env variables

Useful packages


For unit tests: https://github.com/Pallinder/go-randomdata

Go Modules


Inspired by: Getting started with Go modules

To initialize Go modules in to your application you can run:

$ go mod init /path/to/directory

Example shows that we need to include the path:

root@bc7429fce4a8:~/TestApp# go mod init 
go: cannot determine module path for source directory /root/TestApp (outside GOPATH, no import comments)

root@bc7429fce4a8:~/TestApp# ls
main.go

root@bc7429fce4a8:~/TestApp# go mod init /root/TestApp
go: creating new go.mod: module /root/TestApp

root@bc7429fce4a8:~/TestApp# ls
go.mod main.go

root@bc7429fce4a8:~/TestApp# cat go.mod

module /root/TestApp

# go run main.go 
go: finding github.com/Pallinder/go-randomdata v1.1.0
go: downloading github.com/Pallinder/go-randomdata v1.1.0
Running the TestApp
Backstump

root@bc7429fce4a8:~/TestApp# go run main.go 
Running the TestApp
Frightbrown

# cat go.mod 
module /root/TestApp

require github.com/Pallinder/go-randomdata v1.1.0 // indirect

root@bc7429fce4a8:~/TestApp# cat go.sum
github.com/Pallinder/go-randomdata v1.1.0 h1:gUubB1IEUliFmzjqjhf+bgkg1o6uoFIkRsP3VrhEcx8=
github.com/Pallinder/go-randomdata v1.1.0/go.mod h1:yHmJgulpD2Nfrm0cR9tI/+oAgRqCQQixsA8HyRZfV9Y=

If we want to change version of the 3rd party package (go-randomdata in our case) we just need to manually edit the go.mod and set there desired version. go run (or go build) would then apply that version and hashes in go.sum would also change.

TBC...