Learning Golang as Your Second Programming Language: Learning Paths, Best Practices, and Engineering
This article is for those who have some programming background and are considering learning Golang as their second programming language. I hope to provide some direction for your learning journey.
Overview
Introduced in 2009 and backed by Google, Go, designed by computing pioneers Robert Griesemer, Rob Pike, and Ken Thompson, is a statically typed, compiled, cross-platform language with concurrency support at the language level, garbage collection, and a syntax within the tradition of the C programming language.
Due to the commonality of the word go, leading to potential ambiguity, the community often refers to the Go language as Golang
, which tends to yield more relevant search results.
Golang is currently at a major version of v1, typically releasing a minor version every six months (1.x) and patch/security updates every few days to weeks (1.x.y), promising backward compatibility within major versions, allowing for worry-free upgrades.
Golang is a relatively stable, constrained, and conservative language, with few language features and a lengthy process for introducing new features, often taking at least a year, so there’s no need to worry about being overwhelmed by new language features.
Golang has become the de facto language of cloud-native development. Here are some widely used projects:
- Golang: The Go language is self-bootstrapping (Who came first? the chicken or the egg? Since Go 1.5, 2015).
- Kubernetes: The de facto enterprise container orchestration solution.
- Docker: The pioneering containerization technology, leading the market.
- Istio: A service mesh for containerized networks.
- Prometheus: The industry standard for application metric monitoring.
- InfluxDB: A time-series database.
- TiDB: A distributed SQL database.
Golang is widely used by leading teams around the globe, including Google, Cloudflare, Microsoft, Paypal, DropBox, Twitter, Uber, Netflix, HashiCorp, Alibaba, Tencent, Baidu, PingCAP, Qiniu and Riot Games.
Learning Path
The most effective way to learn is by building several projects after grasping the basics of the language. Learn by doing and build as you learn.
Language Fundamentals
- Start by visiting the Golang official website for language environment setup.
- Work through the hands-on official tutorial on your PC. The tutorial will familiarize you with most features of Golang, requiring about 2 hours to complete.
- Bookmark Go by Example for quick reference on how to use specific features.
- Start writing some projects to apply what you’ve learned.
IDE
Common IDE options include:
- Visual Studio Code + Golang extension: Free, with support from the official Golang team.
- GoLand: Paid, from JetBrains, the same company behind IDEA, PhpStorm, and WebStorm.
- vim + vim-go: Free.
- Atom + Go-Plus: Free.
If you haven’t found your preferred IDE above, the official wiki has a comprehensive list.
Dependencies and Documentation
Golang’s standard library is very pragmatic, allowing for most functionalities to be implemented with just the standard library. The list of standard libraries can be found here.
Typically used standard libraries include:
- net/http: HTTP client and server.
- encoding/json: JSON encoding and decoding.
- crypto: Various cryptographic, hashing, and signing methods.
- database/sql: Standardized access to SQL databases.
Go does not require centralized library hosting services, allowing any code repository that follows certain rules to be a valid source for pulling third-party libraries. You can search for third-party libraries on GitHub or search engines and consult their documentation on the official Go Dev site. Go’s documentation is generated from code comments written following specific conventions. For example, my HTTP gzip compression middleware, github.com/nanmu42/gzip
, is documented at: https://pkg.go.dev/github.com/nanmu42/gzip
Some commonly used third-party libraries include:
- github.com/gin-gonic/gin: An HTTP framework that includes routing, middleware, request binding, and validation.
- go.uber.org/zap: Structured logging.
- github.com/go-gorm/gorm: ORM for various SQL databases.
- github.com/go-pg/pg/v10: PostgreSQL client.
- github.com/go-sql-driver/mysql: MySQL driver.
- github.com/go-redis/redis/v8: Redis client.
- github.com/segmentio/kafka-go: Kafka client.
- github.com/elastic/go-elasticsearch: Elasticsearch client.
- github.com/mongodb/mongo-go-driver: MongoDB client.
Advanced Learning
- The Go Programming Language: Written by members of the Golang team.
- Official recommended learning resources
- Selected articles from the official blog
- Language specification
Best Practices
Language Style
Programming is both a process of creating possibilities and a process of eliminating them.
The language style advocated by Golang pursues simplicity, clarity, and order:
- Simplicity and Clarity: The language has a minimal set of keywords and a concise API.
- Order (Constraint): Practices like CSP (Communicating Sequential Processes),
gofmt
for code formatting, and static analysis for code quality.
Eliminating possibilities makes the correct approach obvious, and order can improve team productivity significantly.
gofmt/goimports
In many programming languages, formatting code can be a source of endless debate: tabs or spaces? Should array elements at the end include a comma? Should the opening brace of a function be on a new line? The lack of unified tooling or too many options in existing tools can make code reviews more challenging due to formatting inconsistencies.
gofmt
formats Go code, standardizing formatting across all code without providing any configuration options. When everyone on a team uses gofmt
, all code looks the same, eliminating debates on formatting.
goimports
is an enhanced version of gofmt
that, in addition to formatting code, also sorts and adjusts imports for greater consistency. In practice, it’s commonly used in place of gofmt
.
Static Analysis
While Golang’s compilation provides a basic guarantee of code correctness, it’s not always sufficient. Static analysis involves finding errors, suspicious patterns, or potential optimizations before the code is compiled.
Golang’s tooling ecosystem, including its ability to self-bootstrap, means there are extensive tools for parsing and analyzing code. One notable tool is golangci-lint, which integrates numerous linters for various checks, such as govet
for suspicious constructs, ineffassign
for unused variables, errcheck
for unchecked errors, and gosimple
for code simplification suggestions.
Like gofmt
/goimports
, integrating golangci-lint
into your IDE’s save hook can immediately identify and notify you of issues as you code.
Comments and Documentation
The official guide, Effective Go, outlines best practices for writing comments that can generate documentation.
Documentation should be concise and relevant, focusing on:
- Package descriptions.
- Public (exported) functions, structures and their methods, variables, and constants.
- Complex business or algorithmic processes.
- Work in progress (TODOs).
Particularly useful areas for documentation include:
- APIs with high degrees of freedom or multiple possible implementations, often involving
interface{}
or visitor patterns, where more explicit documentation can prevent misuse. - Temporary solutions, clarifying the intent and the expected permanent solution.
Places where documentation may be less necessary include:
- Private (unexported) variables, structures, and methods with limited scope.
- Functions and methods where names, parameters, and their types clearly indicate their use.
- Straightforward processes.
Testing
Testing can detect implementation errors, regression bugs, and unintended changes, enhancing delivery efficiency and confidence. If you find yourself manually testing a feature repeatedly, consider writing automated tests for it.
Go natively supports testing, with clear tutorials and documentation provided officially.
Some IDEs (like GoLand and Visual Studio Code) offer quick ways to generate test boilerplate, which can save time.
If your tests require databases or external resources, consider using dockertest to dynamically launch disposable containerized instances during testing, reducing the tests’ environmental dependencies.
Compilation and Deployment
Binaries
Go supports compiling binaries for Linux, Windows, and Mac. The compiled binaries include the complete Go runtime along with your program, making them directly executable on devices with the same system architecture.
Depending on your code’s complexity and dependencies, binary sizes typically range from a few MBs to tens of MBs.
Cross-compilation is possible across these platforms if your code doesn’t include cgo. Tools like Gox can simplify cross-compilation, although they are not strictly necessary. If your code includes cgo and you need cross-compilation, xgo might meet your needs by providing a CLI tool and containerized environment for cross-compilation.
For embedding static files (e.g., packaging a frontend application within a binary), consider using the embed feature introduced in Go 1.16.
Containerization
Given Go’s binary output, images can be extremely lightweight, even based on scratch
. Here’s a reference Dockerfile
:
|
|
In production, consider using Alpine as the base image for debugging and troubleshooting purposes while also managing timezone information and CA certificates more conveniently:
|
|
Engineering Practices
HTTP Services
For HTTP services, gin-gonic/gin is recommended for its efficient handling of routing, middleware, request binding, and validation. Here’s a scaffold project example to get started.
Alternatively, you can rely on the standard library’s net/http
, but it means you’ll need to handle more tasks manually.
Most Go HTTP frameworks, including Gin, are built on top of net/http
, adopting a “goroutine per connection” strategy. This approach allows for blocking-style development of controllers and performs well under typical workloads.
For extremely high-load services, consider implementing rate limiting, circuit breaking, or a goroutine pool, and possibly switching to gnet for handling business logic. This can complicate the service but may be necessary to avoid bottlenecks.
CLI Programs
For command-line applications, spf13/cobra offers tools and a structured way to build them with ease, providing convenient methods for parsing commands and flags.
Other Considerations
- Go can compile to WebAssembly under certain conditions, allowing execution in web browsers or Node.js.
- While not mainstream, Go can be used for GUI applications, with Fyne being a potential framework.
- For integrating Go-written dependencies on Android or iOS, the official Go Mobile project might be useful.
Tool Recommendations
These tools aren’t necessary but can greatly enhance your coding experience:
- JSON-to-Go: Instantly generate Go structs from JSON.
- Gopherize.me: Customize a Gopher logo for your project.