The Go Programming Language is the premier Go book. It is similar in purpose to The C Programming Language which I consider one of the few must-read books for any programmer.

The Go Programming Language covers the core language very well, dives into more advanced language features, gives an overview of how your code fits into the world with packages and tooling and finally showcases some rarely used language features.

The core language consists of discussions about types (int, runes/characters, etc.), control flow, scopes, arrays, slices, and maps.

Next, I would consider advanced features to be Go’s approach to interfaces and object-oriented programming along with the chapters about channels and concurrency. These middle chapters were perhaps the most interesting with practical advice on how and when to use the language features.

Giving an overview of packages and the go tooling, it really shows how you can consume and produce production code. Go 1.11’s module system has made some of the text outdated, but some of the advice is probably under-appreciated at first glance like how to benchmark and profile code using the Go tools.

Finally, the book does a brief into to reflection and how to interact with C code. While a bit lighter (and the authors admittedly believe that these features are not commonly used in most Go code), I have started appreciating any language’s ability to interact with C code. Reflection has also been useful when I was programming in Java, and I imagine whenever you have to write a marshaller/encoder for a custom format, it will be just as useful.

While someone without programming experience can pick up this book, several of the concepts such as concurency, closures, and object oriented programming are only briefly discussed before diving into the application of those concepts with Go. Several chapters felt like they needed prior programming experience with a different programming language to appreciate what the authors were illustrating with their examples and explanations.

A Tour of Go gives most programmers enough to start programming in Go. However, this book goes further in explaining what is idiomatic Go code. For example, it gives an explanation on Go’s philiosophy on error handling, explains why Go does not have a set type, and discusses why the testing package is so sparse without assertions compared to other languages’ testing libraries. Whether or not you agree with the design decisions, having those explanations in mind will lead to more idiomatic Go code.

My suggestion for anyone looking to pick up Go is to work through A Tour of Go, write or port a few simple programs from another language to Go, and then read The Go Programming Language. You may discover several tips (like how to create internal packages, why there is a doc.go file in packages, why slices are not comparable, and embedded/anonymous struct fields). Go does make it “easy to build simple, reliable, and efficient software”, but there are still conventions, inconsistencies, and fairly uncommon language features which are well explained in The Go Programming Language.

Writing An Interpreter In Go is a a fun book which covers writing an end to end interpreter in Go. I took a compiler course at my university which required reading the dragon book, but I feel that this book was a great and to-the-point guide in building your own language. While it doesn’t cover the theory, the intent is a straightforward text to introduce you to interpreters/compilers.

You write a lexer, parser, and the evaluating interpreter in Go from scratch without any third party dependencies. It is fast-paced with an encouraging tone which celebrates your accomplishments. The full code is provided, but I found it helpful to write and then play around with the code to fully understand it. I hadn’t written any significant Go programs before so it was helpful in learning the language.

The book guides the reader to implement the Monkey language. Monkey is fairly featured and covers basic expressions, functions, arrays, hashes, built-ins, closures, and a bit more.

While I haven’t written an end-to-end compiler since college, many of the concepts especially lexing/parsing are useful in a wide range of problems. Knowing how a compiler works is fundamental to advancing programming skills at a certain point. Reading this book has made me appreciate again how important those skills are in a relatively short and practical text.

There is a lost chapter available for free which implements a macro system and a sequel book to implement a bytecode compiler. I intend to read both in the future.

Terraform has a TLS Provider for generating certificates. It can generate a CA, certificates signed by a CA, self-signed certificates, and a bit more.

(Note: While you should not use tls_private_key in production environments (because the data is not encrypted in the Terraform state), it is great for development environments.)

Here’s an example Terraform file which generates a CA and a signed certificate which you can use with your own web server:

provider "tls" {
  version = "~> 1.2"
}

provider "local" {
  version = "~> 1.1"
}

resource "tls_private_key" "acme_ca" {
  algorithm = "RSA"
  rsa_bits  = "4096"
}

resource "local_file" "acme_ca_key" {
  content  = "${tls_private_key.acme_ca.private_key_pem}"
  filename = "${path.module}/certs/acme_ca_private_key.pem"
}

resource "tls_self_signed_cert" "acme_ca" {
  key_algorithm     = "RSA"
  private_key_pem   = "${tls_private_key.acme_ca.private_key_pem}"
  is_ca_certificate = true

  subject {
    common_name         = "Acme Self Signed CA"
    organization        = "Acme Self Signed"
    organizational_unit = "acme"
  }

  validity_period_hours = 87659

  allowed_uses = [
    "digital_signature",
    "cert_signing",
    "crl_signing",
  ]
}

resource "local_file" "acme_ca_cert" {
  content  = "${tls_self_signed_cert.acme_ca.cert_pem}"
  filename = "${path.module}/certs/acme_ca.pem"
}

resource "tls_private_key" "example_com" {
  algorithm = "RSA"
  rsa_bits  = "4096"
}

resource "local_file" "example_com_key" {
  content  = "${tls_private_key.example_com.private_key_pem}"
  filename = "${path.module}/certs/example_com_private_key.pem"
}

resource "tls_cert_request" "example_com" {
  key_algorithm   = "RSA"
  private_key_pem = "${tls_private_key.example_com.private_key_pem}"

  dns_names = ["example.com"]

  subject {
    common_name         = "example.com"
    organization        = "Example Self Signed"
    country             = "US"
    organizational_unit = "example.com"
  }
}

resource "tls_locally_signed_cert" "example_com" {
  cert_request_pem   = "${tls_cert_request.example_com.cert_request_pem}"
  ca_key_algorithm   = "RSA"
  ca_private_key_pem = "${tls_private_key.acme_ca.private_key_pem}"
  ca_cert_pem        = "${tls_self_signed_cert.acme_ca.cert_pem}"

  validity_period_hours = 87659

  allowed_uses = [
    "digital_signature",
    "key_encipherment",
    "server_auth",
    "client_auth",
  ]
}

resource "local_file" "example_com_cert_pem" {
  content  = "${tls_locally_signed_cert.example_com.cert_pem}"
  filename = "${path.module}/certs/example_com_cert.pem"
}