Go, developed at Google by industry veterans Rob Pike, Ken Thompson, and Robert Griesemer, released in 2012. Despite initial scrutiny due to its perceived simplicity, Go has gained popularity for addressing key issues in software development
- Readability
- Fast compilation
- Controlled dependencies
- Cross-environment builds
Go intended to address these issues and more at the language level.
Key language features
Concise language grammar
With only 25 keywords (compared to C's 60 and C++20's 97), Go offers a low barrier to entry while remaining powerful enough to compete with C/C++ in certain domains like web servers.
Streamlined syntax
Go's syntax prioritizes readability and consistency. For example, the versatile for
loop can also simulate while loops and infinite loops:
// standard C-style for loop
for i := 5; i > 0; i-- {
fmt.Println(i)
}
// while loop
i := 5
for i > 0 {
fmt.Println(i)
i--
}
// infinite loop
for {
fmt.Println("I'm infinite!")
}
Go's if
statements have also been enhanced with the option to include a short statement before the condition is evaluated, scoped to the if-else block:
if num, err := strconv.Atoi(str); err != nil {
fmt.Println("Error: ", err)
} else {
fmt.Println("Integer value of string: ", num)
}
// num and err cannot be referenced after its scope
Resource management
Go's defer
keyword ensures proper resource cleanup once the scope in which it was created has terminated:
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("Error: ", err)
return
}
defer file.Close()
// file will be closed when this scope is terminated
Error handling
Go uses explicit error returns instead of exceptions:
file, err := os.Open("example.txt")
// os.Open returns a value of type (*File, *PathError)
if err != nil {
return fmt.Errorf("something went wrong: %w", err)
}
defer file.Close()
// use file
This approach encourages immediate error handling and avoids complex try-catch structures. You essentially build a stack trace as the error gets propagated up the call stack, which can then be logged.
Built-in concurrency
Go's goroutines and channels make concurrent programming straightforward. Goroutines offer lightweight threads and channels provide communication across threads:
resultChan := make(chan int)
// spawn goroutine
go func() {
// perform some calculation
resultChan <- value
}()
// block thread until something can be read from the channel
value := <-resultChan
These features combine to create a language that's easy to learn, read, and maintain, without sacrificing power or efficiency.
Go's efficiency
Simplified dependencies
Go addresses the complex dependency issues of languages like C and C++ with a streamlined approach. The compiler only looks at package object files, not source files. This reduces redundant I/O and processing operations, resulting in significantly faster compile times.
Let's look at an example. Package A imports package B which imports package C. First C is compiled. Next B is compiled, pulling in necessary information from C into its object file. Finally, A is compiled, only needing to look at one file, the object file for B.
Static and cross-compilation
Go is statically compiled. This means all imported packages, including the standard library, are compiled together into a single binary. Go can also cross-compile to target different operating systems and architecture combinations using the GOOS and GOARCH environment variables.
For example, if I develop on MacOS and/or Windows and want to deploy to an AWS T3 instance which runs Linux with x86 architecture, I could build my binary like this:
GOOS=linux GOARCH=amd64 go build myapp
These features make Go applications easy to deploy and makes "it works on my machine" issues less common.
The future of Go
The Go team has committed to backwards compatibility. No breaking changes in future versions ensures long-term stability and easy maintenance of legacy code.
Go has been adopted by major companies for various application: Docker, Kubernetes, and Terraform are built with Go. Companies like Google, Netflix, Paypal, an Uber use Go internally.
Go's simplicity, efficiency, and stability make it an attractive option for developers tackling complex problems. As the language continues to grow, it's becoming an increasingly valuable tool in the software development ecosystem.