Skip to content
jeffkayser2 edited this page Apr 5, 2019 · 23 revisions

Learning about Go programming

Books: https://github.com/golang/go/wiki/Books

I have purchased a large number of Go books. (Watch for Packt specials. They had a sale where each tech book was $5, so I bought 20 books, mostly about Go.) My favorites:

The Go Programming Language

Authors: Alan A. A. Donovan · Brian W. Kernighan

Yes, this is the Brian Kernighan of Unix fame: https://en.wikipedia.org/wiki/Brian_Kernighan

This book reminds me of the K&R C book. Will probably be as impactful. This is my main Go book.

Hands-On Dependency Injection in Go

Author: Corey Scott

Very insightful. Dependency injection can help resolve circular package references. This is a big deal, because with Go, if you have circular package references, your program will not compile.

Go In Action

Authors: William Kennedy with Brian Ketelsen and Erik St. Martin

It's a good book, covering some of the same material as the previous book, but also bit and pieces of other useful Go stuff.

William has a really great Golang blog too: https://www.ardanlabs.com/blog/

Go Web Programming

Author: Sau Sheong Chang

Goes into more details about the web programming aspects of Go. During the book, the author builds a complete web app in Go.

Resources for new Go developers:

https://dave.cheney.net/resources-for-new-go-programmers

Common pitfalls for new Go developers:

http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/

Go proverbs:

https://go-proverbs.github.io/

What I like about Go

  1. Designed to be simple and easy to program. Usually only one well-thought-out way to do something. Language design goals here: https://talks.golang.org/2012/splash.article Looks like C, so if you know C programming, the syntax will be more familiar.
  2. There is an idiomatic way of writing Go code, and if you follow the Go idioms, you will be more successful programming in Go. The idioms are best described here: https://golang.org/doc/effective_go.html
  3. Easy to use, high quality tooling makes it easy to run programs, to build binaries, to format your code, to document your code in a standard way, to display documentation, to test programs, etc. See: https://golang.org/cmd/go/
  4. Very complete, high quality, built-in packages (libraries). https://golang.org/pkg/ Also, a growing body of open source code.
  5. Go is exceptionally well suited for web services programming. Web service programming fits naturally to the main Go programming model (goroutines, channels, etc.); no impedance mismatch. Go has strong library support for all things web related (HTTP clients and servers, the latest SSL support, built-in support for HTTP/2, a wonderful templating engine to generate text and HTML, etc.) Instead of LAMP (Linux, Apache, MySQL, and PHP), you can have LMG (Linux, MySQL and Go, with Go replacing both Apache and PHP). And, if you use a pure Go database engine (like https://godoc.org/modernc.org/ql), it can be simply Linux (or Windows) and Go.
  6. You can organize code in packages, and combine related functionality together in a single, reusable building block. Note: Package dependencies cannot be cyclic (e.g. package A depends on B, and package B depends on A -- not allowed; you will get a compiler error). This has implications for how you structure a Go program. The best article I have found describing those implications, and how to deal with them is: https://dave.cheney.net/2016/08/20/solid-go-design Another helpful link: http://stackoverflow.com/questions/20380333/cyclic-dependencies-and-interfaces-in-golang An architecture which support this is: http://manuel.kiessling.net/2012/09/28/applying-the-clean-architecture-to-go-applications/
  7. The Go community has finally converged on a single package management methodology: modules. Francesc Campoy has a good introduction to it in his "Just For Func" series: https://www.youtube.com/watch?v=aeF3l-zmPsY. He also does a good job describing semantic versioning. With the semver example of v1.2.3, Francesc suggests that, instead of thinking of (1,2,3) as (major version, minor version, bug fix), you should think of it as (breaks backward compatibility, adds new functionality, fixes bugs). Really good insight. Modules look great!
  8. Simple private/public model for package variable visibility. Variables that begin with uppercase letters are visible to callers outside the package, and variables that don't are private to the package.
  9. Variables are statically typed. The compiler ensures that you only assign values to variables that are the appropriate type, so you can't store the wrong type of data in a variable. This eliminates a whole class of programming errors that affect dynamically-typed languages (like Python).
  10. Compiled. The (fast) compiler catches many errors that, if you were using a dynamically-typed scripting language (like Perl or Python), could only be caught by testing.
  11. Compiler generates statically-linked standalone binaries. This means
  • Unless you add external dependencies to your Go app (e.g. calling an external database), your binary won't have ANY dependencies. You copy the Go binary (generated by the compiler) to your target machine, and run it. No need to install a Java JVM, a Python or Perl interpreter, third-party libraries, or anything else. This minimizes the impact of deploying your code.
  • To run your program, you distribute binaries instead of source code, so it helps protect intellectual property.
  1. Fast. My favorite Go performance story: https://www.iron.io/how-we-went-from-30-servers-to-2-go/
  2. Cross platform. Most of the libraries work on all the supported platforms. Windows is supported very well (although I would be a liar if I told you that Windows is as well supported as Linux.) When you compile a program, you can generate a binary for any supported platform, and the program will generally run fine. See: https://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5 The best article I found about programming for multiple platforms is here: http://techblog.steelseries.com/2014/04/08/multi-platform-development-go.html To support OSes with different pathing rules (e.g. Windows), use the library functions that allow you to do that in a general way. See: https://golang.org/pkg/path/filepath/
  3. First class functions. Functions can return multiple values by specifying "return" with multiple return values, separated by commas. Functions can return functions, and you can store a function reference in an appropriately typed variable. You can have anonymous functions. No overloading of function definitions. Good article here: https://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions
  4. Error handling. Errors are just values; no exception handling. After a function call, you check the error value returned by the function. Capturing error context can be achieved via add-on packages like: https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package
  5. Semi object-oriented. No class hierarchy or inheritance. Types play the role of classes. You can create custom structures and types of arbitrary complexity. You can attach functions to types like you would attach a method to an object. Then, only instances of those types can use those functions; the syntax makes it easy.
  6. Interface are defined as a (possibly empty) list of function signatures. You can have variables that have an interface type. Interface variables can be assigned any concrete type which satisfies all the function signatures listed for the interface. Interfaces are satisfied implicitly if the type (structure) implements all of the function signatures listed in the interface.
  7. Interfaces allow you to generalize the input to a function. Instead of specifying a concrete type as a function input, specify an interface that lists only the function signatures you require for the input to your function. Then, any concrete type that implements the interface can be passed in as an input to your function.
  8. Built-in support for concurrency. The language has built-in functionality to help with concurrent programming (goroutines, channels, etc.), as well as library support for other stuff related to concurrency (simple mutexes, mutexes that allow for multiple readers and one writer, atomic functions, etc.) Goroutines are very light-weight "threads" managed by the Go runtime, not the OS. Channels are things you use to send and receive data structures, and implicitly handle the synchronization aspect of passing data between concurrent goroutines. "select" language primitive allows multiplexing reads of multiple channels at once.
  9. Concurrent programming is still harder to reason about than programming for a single thread of execution. Some useful references: https://golang.org/doc/effective_go.html#concurrency, https://talks.golang.org/2012/concurrency.slide#1. If you have shared memory with multiple goroutines both reading and writing, you have to serialize access to the shared memory. This can be done in a couple of ways:
  • Define a mutex to protect access to the shared memory. "sync" library has simple mutexes, as well as mutexes that will allow for multiple readers and a single writer. This IS NOT the Go way.

  • Create goroutines that keep the memory local (to the goroutine), and "share" the memory by communicating to other goroutines over channels. This IS the Go way. The Go object "service" can create a copy of the "shared" memory, and send the copy to the caller (over a channel); the master copy of the data is retained by the object "service".

  1. Reflection is supported by the "reflect" package. Useful add-on packages related to reflection: https://blog.gopheracademy.com/birthday-bash-2014/advanced-reflection-with-go-at-hashicorp/
  2. Oracle Database Connectivity. Options for Go connectivity to Oracle databases are described in the presentation "The Go Language: Principles and Practices for Oracle Databases": https://github.com/jeffkayser2/learningGo/blob/master/DEV5047%20-%20Connect%20The%20Go%20Language%20To%20Oracle%20Database.pdf. Unfortunately, there is no Go native Oracle DB driver. However, there is a Go library https://github.com/go-goracle/goracle that is based on an Oracle-created C library ODPI-C: https://github.com/oracle/odpi. More details here: https://oracle.github.io/odpi. This is the best alternative at this time. This blog articles shows how you can use it: https://blogs.oracle.com/developers/how-to-connect-a-go-program-to-oracle-database-using-goracle.