Grafvision - Fotolia
A Go programming language tutorial for IT ops
Go is a diversely applicable programming language that ops admins can use on distributed systems without the complications of traditional languages such as C or Java.
The Go programming language was designed with simplicity in mind, but that does not mean it is limited in what it can do. IT operations engineers use Go to automatically spin up containers, configure networks, provision storage and accomplish other tasks.
Docker containerization was written in Go, as was the container orchestration tool Kubernetes. Go, which was originally developed at Google, is used by the company in various systems, such as the Google App Engine that provides infrastructure abstraction for Google Cloud and the Vitess method for sharding MySQL to scale it.
Go was written by Robert Griesemer, Rob Pike and Ken Thompson at Google. Pike and Thompson's backgrounds include building the original Unix OS at Bell Labs in the 1970s.
Go, also called golang, has similarities to and differences from other programming languages for infrastructure, as well as some limitations to understand before you undertake a golang project. Follow along with the simple Go programming language tutorial here to get a sense of how it works.
Why use Go?
Google developed Go in part to make the rollout of code written by its large project teams easier, according to Pike. One option is to make code shorter. For example, a C-language programmer must put precompiler directives, such as #ifdef for if defined, into the code to tell it what modules to pull in at compile time. That approach can get messy and longwinded. Go, like Python, relies on a simple import directive, which tells each program just to pull in what it needs.
Prior to Go, Google's software build took 45 minutes and a substantial network of servers. Now, it takes 27 minutes. "The origin myth for Go states that it was during one of those 45-minute builds that Go was conceived," Pike said.
Go is statically linked instead of dynamically linked, so Go programs are easy to port. All the shared object libraries, which end in .so, that a program needs are put inside the compiled Go program instead of being called at runtime. In Java terms, that's called a fat JAR. Such code should work on systems that do not already have these dependencies in place and on systems where the objects are mismatched versions.
Use the latest version
If you plan to use Go, download the latest version. What's available in public repositories might not be the latest, or even a supported version of Go. For example, the version in the Ubuntu repository is 1.2.1, while the latest on the Go download site at the time of writing is 1.10.1.
Porting is a problem with other programming languages, including Python. Python organizations want to keep version 2.7 in place and simultaneously support version 3, which leads to assorted problems whenever developers get Python packages mixed up. Go is a compiled programming language, which runs faster than interpreted languages, such as Python. Go compiles much faster than C does. And Go is shorter and more succinct than Java, which also requires complex Apache Maven and Ant config files to build the JAR.
Advanced Go features
While Go has a relatively simple syntax, it supports advanced language features, such as concurrency and functional programming.
functional programming, as will be familiar to Scala and Haskell programmers, enables immutable operation. With functional programming, everything is a function and there are no global variables, so one programmer cannot change global variables in the code and mess it up for other programmers. The behavior of the program depends on the values passed to it. Functional programming is only a style, not a requirement to write Go code.
Concurrency, when a program spins off another thread, is another Go feature that is complicated to implement in other languages. There is the danger that one thread can change a variable value that another thread is also using. Languages such as Java and Python require that the programmer specifically write code to start, stop and wait for a process to run. Go protects shared variables from being overwritten and, worse, deadlocking threads.
The Go programming language can pass variables by reference or value, which is a feature of C as well. For example, Go code can use a memory address, or pointer, to update a variable without making a second copy of it. In C, this setup can cause dangerous and unpredictable errors -- as well as an attack surface for hackers -- but Go memory management is handled the same way as with Java: It creates and destroys objects in memory as they go in and out of scope.
A Go infrastructure programming tutorial
There are many APIs for Go for infrastructure programming for Docker, AWS, OpenStack, SaltStack and a plethora of others. Via Go programming, infrastructure engineers, infrastructure developers, site reliability engineers and similarly titled IT pros orchestrate VM and container deployments, create networks, provision users and storage, and complete other tasks.
For example, with Go and the Amazon software development kit (SDK), a programmer can write code to work with AWS products ranging from CloudTrail compliance monitoring and audits to Simple Storage Service (S3) and Elastic Compute Cloud infrastructure, as well as the DynamoDB NoSQL database service and even serverless Lamda event-driven processing.
With Amazon, the starting point is a session. A session includes, for example, an Amazon region. A Go programmer creates an Amazon S3 client like this:
sess, err := session.NewSessionWithOptions(session.Options{})
s3.New(sess)
Go uses imports to know where to get the Amazon SDK:
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"fmt"
"os"
)
The user can then create an S3 bucket, such as svc.CreateBucket(). An Amazon S3 bucket is like a file folder.
Go programming language limitations
Go does not support generic types. A programmer cannot, for example, declare a function using the ANY type, as they can with Scala. Generic types enable one function to handle any type of parameter. But with Go, the programmer must write one function for each type. For example, doSomething(i int32) works with 32-bit integers, but not 64-bit ones, which need doSomething64(i int64). Google addresses that and other issues in its FAQ on Go.
Go does not support overloading, which is commonly used for tasks such as to test whether two objects are equal. For example, the programmer can overload = (equals) to test whether two objects are equal. That's not possible with Go.
Go's pursuit as a programming language is simplicity. It's for the programmer to decide if this aim comes at the cost of feature richness, or is a way to shirk esoteric, difficult-to-understand fluff.