Learning Golang as Your Second Programming Language: Learning Paths, Best Practices, and Engineering

      ☕ 9 min read
🏷️
  • #Golang
  • 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.

    The mascot for the Go language is the Gopher, and enthusiasts of the Go language often refer to themselves as Gophers. Image by Renee French
    The mascot for the Go language is the Gopher, and enthusiasts of the Go language often refer to themselves as Gophers. Image by Renee French

    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.

    From left, Robert Griesemer (V8 JavaScript engine, Java HotSpot VM), Rob Pike (UNIX, Plan9, UTF-8) and Ken Thompson (B, Unix, UTF-8, grep) Screenshot from Youtube: Google I/O 2012 - Meet the Go Team
    From left, Robert Griesemer (V8 JavaScript engine, Java HotSpot VM), Rob Pike (UNIX, Plan9, UTF-8) and Ken Thompson (B, Unix, UTF-8, grep) Screenshot from Youtube: Google I/O 2012 - Meet the Go Team

    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:

    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:

    Advanced Learning

    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:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    FROM golang:1-alpine as golang
    RUN apk --no-cache add git zip tzdata ca-certificates
    # avoid go path, use go mod
    WORKDIR /app
    COPY . .
    RUN CGO_ENABLED=0 go build -ldflags "-s -w -extldflags "-static"" ./cmd/appnamehere
    WORKDIR /usr/share/zoneinfo
    # -0 means no compression.  Needed because go's
    # tz loader doesn't handle compressed data.
    RUN zip -r -0 /zoneinfo.zip .
    
    
    FROM scratch
    # the timezone data:
    ENV ZONEINFO /zoneinfo.zip
    COPY --from=golang /zoneinfo.zip /
    # the tls certificates:
    COPY --from=golang /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
    # Copy the binary
    COPY --from=golang /app/appnamehere/
    # example ENV: COS secret ID and secret key
    ENV COS_SECRET_ID="" COS_SECRET_KEY=""
    # example EXPOSE
    EXPOSE 3030
    ENTRYPOINT ["/appnamehere"]
    

    In production, consider using Alpine as the base image for debugging and troubleshooting purposes while also managing timezone information and CA certificates more conveniently:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    FROM golang:alpine3.12 as golang
    RUN apk --no-cache add make git zip tzdata ca-certificates nodejs npm gcc musl-dev
    WORKDIR /app
    COPY . .
    RUN make
    
    FROM alpine:3.12
    # Dependencies
    RUN apk --no-cache add tzdata ca-certificates
    # where application lives
    WORKDIR /app
    # Copy the products
    COPY --from=golang /app/bin .
    # env
    ENV GIN_MODE="release"
    EXPOSE 3000
    ENTRYPOINT ["/app/telescope"]
    

    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:

    Share on

    nanmu42
    WRITTEN BY
    nanmu42
    To build beautiful things beautifully.

    What's on this Page