Part 4: Go (Golang)
In Part 4, we introduce Go, also known as Golang. Created at Google by Robert Griesemer, Rob Pike, and Ken
Thompson in 2007, Go was designed to address the challenges of building large-scale software systems. It
combines the speed and safety of compiled languages with the simplicity and productivity of scripting languages.
Go's standout features are its built-in concurrency model using goroutines and channels, fast compilation, and a
minimalist syntax.
4.1 Setting Up Go
Download Go from [Link]. The installation includes the compiler, runtime, and tooling. Go uses a module
system for dependency management. Initialize a new module with go mod init. The go command handles building,
testing, formatting, and dependency management.
$ go version
go version go1.22.0 darwin/amd64
# Initialize a module
$ mkdir myproject && cd myproject
$ go mod init [Link]/myproject
$ go run [Link] # Compile and run in one step
4.2 Hello World in Go
Go programs are organized into packages. Every program must have a main package with a main function, which
serves as the entry point. The fmt package provides formatted I/O similar to C's printf.
package main
import "fmt"
func main() {
[Link]("Hello, World!")
}
4.3 Variables and Data Types
Go is statically typed. Variables can be declared explicitly with var or with the short declaration operator := inside
functions. Go infers the type from the initial value. Basic types include int, float64, string, bool, and byte. Go does
not have implicit type conversions, which prevents many bugs.
package main
import "fmt"
func main() {
// Explicit declaration
var age int = 30
var name string = "Alice"
var pi float64 = 3.14159
var isReady bool = true
// Type inference with var
Page 1
Part 4: Go (Golang)
var city = "New York"
// Short declaration (only inside functions)
count := 42
x, y := 10, 20 // Multiple assignment
// Constants
const MaxRetries = 3
const Pi = 3.14159
[Link]("%s is %d, lives in %s\n", name, age, city)
[Link]("x=%d, y=%d, count=%d\n", x, y, count)
[Link]("Pi=%.5f, Ready=%v\n", Pi, isReady)
}
4.4 Control Flow
Go's control flow is simpler than most languages. There is only one loop construct: the for loop, which can act as a
while loop. Go also has if-else and switch statements. Notably, conditions in if and for do not require parentheses.
package main
import "fmt"
func main() {
score := 85
// If-else (no parentheses needed)
if score >= 90 {
[Link]("Grade: A")
} else if score >= 80 {
[Link]("Grade: B")
} else {
[Link]("Grade: F")
}
// For loop (traditional)
for i := 0; i < 5; i++ {
[Link]("Iteration %d\n", i)
}
// For loop as while
count := 0
for count < 3 {
[Link]("Count: %d\n", count)
count++
}
// Range-based for loop
fruits := []string{"apple", "banana", "cherry"}
for index, value := range fruits {
[Link]("%d: %s\n", index, value)
Page 2
Part 4: Go (Golang)
// Switch
day := 3
switch day {
case 1:
[Link]("Monday")
case 2:
[Link]("Tuesday")
case 3:
[Link]("Wednesday")
default:
[Link]("Another day")
}
// Switch with no expression (like if-else chain)
switch {
case score >= 90:
[Link]("Excellent")
case score >= 80:
[Link]("Good")
default:
[Link]("Needs work")
}
}
4.5 Functions
Go functions can return multiple values, which is a distinctive and useful feature. Functions are first-class values
and can be passed as arguments. Go also supports named return values and closures.
package main
import "fmt"
// Multiple return values
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, [Link]("division by zero")
}
return a / b, nil
}
// Named return values
func swap(a, b int) (first, second int) {
first = b
second = a
return // naked return uses named values
}
// Variadic function
Page 3
Part 4: Go (Golang)
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
// Function as value
default:
[Link]("Needs work")
}
}
// Closure
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
result, err := divide(10, 3)
if err != nil {
[Link]("Error:", err)
} else {
[Link]("10 / 3 = %.2f\n", result)
}
a, b := swap(1, 2)
[Link]("Swapped: %d, %d\n", a, b)
[Link]("Sum:", sum(1, 2, 3, 4, 5)) // 15
next := counter()
[Link](next()) // 1
[Link](next()) // 2
[Link](next()) // 3
}
4.6 Structs and Methods
Go does not have classes, but it has structs and methods. Methods are functions with a receiver argument. This is
Go's approach to object-oriented programming. You can associate methods with any type, not just structs.
package main
import "fmt"
Page 4
Part 4: Go (Golang)
type Rectangle struct {
Width float64
Height float64
}
// Method with value receiver
func (r Rectangle) Area() float64 {
return [Link] * [Link]
}
// Method with pointer receiver (can modify the struct)
func (r *Rectangle) Scale(factor float64) {
[Link] *= factor
[Link] *= factor
}
// Constructor (convention, not built-in)
func NewRectangle(w, h float64) *Rectangle {
return &Rectangle{Width: w, Height: h}
}
func main() {
rect := Rectangle{Width: 5, Height: 3}
[Link]("Area: %.2f\n", [Link]()) // 15
[Link](2)
[Link]("After scale: %.1f x %.1f\n", [Link], [Link])
[Link]("New area: %.2f\n", [Link]()) // 60
}
4.7 Interfaces
Interfaces in Go are satisfied implicitly. A type implements an interface by implementing its methods, without
explicit declaration. This enables decoupled, flexible designs. The empty interface interface{} (or any in Go 1.18+)
is satisfied by all types.
package main
import "fmt"
type Shape interface {
Area() float64
Perimeter() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
Page 5
Part 4: Go (Golang)
return 3.14159 * [Link] * [Link]
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * [Link]
}
type Square struct {
Side float64
}
func (s Square) Area() float64 {
return [Link] * [Link]
}
func (s Square) Perimeter() float64 {
return 4 * [Link]
}
func describe(s Shape) {
[Link]("Area: %.2f, Perimeter: %.2f\n", [Link](), [Link]())
}
func main() {
c := Circle{Radius: 5}
s := Square{Side: 4}
describe(c) // Circle satisfies Shape
describe(s) // Square satisfies Shape
// Using interface slice
shapes := []Shape{c, s}
for _, shape := range shapes {
[Link]("Area: %.2f\n", [Link]())
}
}
4.8 Concurrency: Goroutines and Channels
Concurrency is Go's signature feature. A goroutine is a lightweight thread managed by the Go runtime. Launch
one with the go keyword. Channels are typed conduits for communication between goroutines. The select
statement lets a goroutine wait on multiple channel operations.
package main
import (
"fmt"
"sync"
"time"
)
Page 6
Part 4: Go (Golang)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
[Link]("Worker %d started job %d\n", id, j)
[Link]([Link]) // Simulate work
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Start 3 workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send 5 jobs
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 5; a++ {
[Link]("Result: %d\n", <-results)
}
// WaitGroup for synchronization
var wg [Link]
for i := 0; i < 3; i++ {
[Link](1)
go func(id int) {
defer [Link]()
[Link]("Goroutine %d done\n", id)
}(i)
}
[Link]()
[Link]("All goroutines finished")
}
4.9 Error Handling
Go handles errors as values, not exceptions. Functions return an error as the last return value, and the caller
checks it. The idiomatic pattern is if err != nil. This explicit approach makes error handling visible in the code.
package main
import (
"errors"
Page 7
Part 4: Go (Golang)
"fmt"
)
func sqrt(x float64) (float64, error) {
if x < 0 {
return 0, [Link]("cannot sqrt negative number")
}
z := 1.0
for i := 0; i < 10; i++ {
z -= (z*z - x) / (2 * z)
}
return z, nil
}
func main() {
result, err := sqrt(16)
if err != nil {
[Link]("Error:", err)
return
}
[Link]("sqrt(16) = %.4f\n", result)
_, err = sqrt(-1)
if err != nil {
[Link]("Error:", err)
}
}
4.10 Summary of Part 4
We covered Go fundamentals including package structure, variables, control flow, functions with multiple returns,
structs and methods, interfaces, goroutines and channels for concurrency, and error handling. Go's simplicity, fast
compilation, and built-in concurrency make it ideal for microservices and networked applications. In Part 5, we
compare all four languages and discuss advanced topics.
Page 8