Go
#12
TIOBE#7
PYPL#12
GitHub#20
RedMonk#12
IEEESpectrum#8
JetBrains#11
Programming Language
Go
Overview
Go is a simple and high-performance programming language developed by Google.
Details
Go was developed in 2009 by Robert Griesemer, Rob Pike, and Ken Thompson at Google as an open-source programming language. It features simple and readable syntax, fast compilation, and excellent concurrency capabilities. While having garbage collection, it achieves high performance and is suitable for large-scale system development. It's particularly popular for developing microservices, cloud applications, and DevOps tools, with important tools like Docker, Kubernetes, and Prometheus written in Go.
Code Examples
Hello World
package main
import "fmt"
// Basic output
func main() {
fmt.Println("Hello, World!")
// Output using variables
message := "Hello, Go!"
fmt.Println(message)
// Output using format strings
name := "John"
age := 25
fmt.Printf("My name is %s and I am %d years old.\n", name, age)
}
Variables and Types
package main
import "fmt"
func main() {
// Basic types
var name string = "John"
var age int = 25
var height float64 = 175.5
var isActive bool = true
// Short form variable declaration
city := "Tokyo"
temperature := 22.5
// Multiple variable declaration
var (
firstName string = "John"
lastName string = "Doe"
score int = 85
)
// Constants
const Pi = 3.14159
const MaxUsers = 100
fmt.Printf("Name: %s, Age: %d, Height: %.1fcm\n", name, age, height)
fmt.Printf("City: %s, Temperature: %.1f°C\n", city, temperature)
fmt.Printf("Full name: %s %s, Score: %d\n", firstName, lastName, score)
fmt.Printf("Pi: %g, Max users: %d\n", Pi, MaxUsers)
}
Arrays, Slices, and Maps
package main
import "fmt"
func main() {
// Arrays (fixed length)
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
fruits := [3]string{"apple", "banana", "orange"}
// Slices (variable length)
colors := []string{"red", "blue", "green"}
colors = append(colors, "yellow") // Add element
// Create slice with make function
scores := make([]int, 3, 5) // length 3, capacity 5
scores[0] = 85
scores[1] = 92
scores[2] = 78
// Maps (dictionaries)
person := map[string]interface{}{
"name": "John Doe",
"age": 30,
"city": "Tokyo",
}
// Create map with make function
grades := make(map[string]int)
grades["Math"] = 85
grades["English"] = 92
grades["Science"] = 78
fmt.Printf("Array: %v\n", numbers)
fmt.Printf("Fruits: %v\n", fruits)
fmt.Printf("Colors: %v\n", colors)
fmt.Printf("Scores: %v\n", scores)
fmt.Printf("Person: %v\n", person)
fmt.Printf("Grades: %v\n", grades)
}
Functions
package main
import "fmt"
// Basic function
func add(a, b int) int {
return a + b
}
// Multiple return values
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil
}
// Named return values
func rectangle(width, height float64) (area, perimeter float64) {
area = width * height
perimeter = 2 * (width + height)
return // Named return values are automatically returned
}
// Variadic parameters
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
// Higher-order function (takes function as parameter)
func applyOperation(a, b int, operation func(int, int) int) int {
return operation(a, b)
}
func main() {
// Function calls
result := add(10, 5)
fmt.Printf("10 + 5 = %d\n", result)
// Handle multiple return values
quotient, err := divide(10, 3)
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Printf("10 ÷ 3 = %.2f\n", quotient)
}
// Named return values
area, perimeter := rectangle(5, 3)
fmt.Printf("Rectangle - Area: %.1f, Perimeter: %.1f\n", area, perimeter)
// Variadic parameters
total := sum(1, 2, 3, 4, 5)
fmt.Printf("Sum: %d\n", total)
// Higher-order function
multiply := func(x, y int) int { return x * y }
product := applyOperation(4, 6, multiply)
fmt.Printf("4 × 6 = %d\n", product)
}
Structs and Methods
package main
import "fmt"
// Struct definition
type Person struct {
Name string
Age int
City string
}
// Method definition (function with receiver)
func (p Person) GetInfo() string {
return fmt.Sprintf("%s (%d years old, lives in %s)", p.Name, p.Age, p.City)
}
// Pointer receiver (for modifying struct)
func (p *Person) SetAge(newAge int) {
p.Age = newAge
}
// Embedding (inheritance-like feature)
type Employee struct {
Person // Embed Person
JobTitle string
Salary int
}
func (e Employee) GetJobInfo() string {
return fmt.Sprintf("%s - Job: %s, Salary: $%d", e.GetInfo(), e.JobTitle, e.Salary)
}
func main() {
// Create struct instance
person1 := Person{
Name: "John Doe",
Age: 25,
City: "Tokyo",
}
// Access fields
fmt.Println("Name:", person1.Name)
fmt.Println("Age:", person1.Age)
// Call method
fmt.Println(person1.GetInfo())
// Call pointer receiver method
person1.SetAge(26)
fmt.Println("Updated:", person1.GetInfo())
// Embedded struct
employee := Employee{
Person: Person{
Name: "Jane Smith",
Age: 30,
City: "Osaka",
},
JobTitle: "Engineer",
Salary: 50000,
}
fmt.Println(employee.GetJobInfo())
}
Interfaces
package main
import "fmt"
// Interface definition
type Shape interface {
Area() float64
Perimeter() float64
}
// Rectangle struct
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// Circle struct
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}
// Function that accepts interface
func printShapeInfo(s Shape) {
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}
func main() {
rectangle := Rectangle{Width: 5, Height: 3}
circle := Circle{Radius: 2}
// Treat as same interface
printShapeInfo(rectangle)
printShapeInfo(circle)
// Interface slice
shapes := []Shape{rectangle, circle}
for i, shape := range shapes {
fmt.Printf("Shape %d: ", i+1)
printShapeInfo(shape)
}
}
Goroutines (Concurrency)
package main
import (
"fmt"
"sync"
"time"
)
// Basic goroutine
func sayHello(name string) {
for i := 0; i < 3; i++ {
fmt.Printf("Hello %s! (%d)\n", name, i+1)
time.Sleep(100 * time.Millisecond)
}
}
// Synchronization with WaitGroup
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // Call Done() when function exits
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
// Basic goroutines
go sayHello("Alice")
go sayHello("Bob")
// Wait a bit in main goroutine
time.Sleep(400 * time.Millisecond)
fmt.Println("---")
// Synchronized processing with WaitGroup
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // Increment counter
go worker(i, &wg)
}
wg.Wait() // Wait for all goroutines to complete
fmt.Println("All workers completed")
}
Channels (Communication in Concurrency)
package main
import (
"fmt"
"time"
)
// Basic channel
func sender(ch chan string) {
messages := []string{"Hello", "Go", "Channels"}
for _, msg := range messages {
ch <- msg // Send to channel
time.Sleep(100 * time.Millisecond)
}
close(ch) // Close channel
}
// Buffered channel
func bufferedChannelExample() {
ch := make(chan int, 3) // Buffer size 3
// Send data asynchronously
go func() {
for i := 1; i <= 5; i++ {
ch <- i
fmt.Printf("Sent: %d\n", i)
}
close(ch)
}()
// Receive data
for value := range ch {
fmt.Printf("Received: %d\n", value)
time.Sleep(200 * time.Millisecond)
}
}
// Select for controlling multiple channels
func selectExample() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(100 * time.Millisecond)
ch1 <- "Channel 1"
}()
go func() {
time.Sleep(200 * time.Millisecond)
ch2 <- "Channel 2"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("From ch1:", msg1)
case msg2 := <-ch2:
fmt.Println("From ch2:", msg2)
case <-time.After(300 * time.Millisecond):
fmt.Println("Timeout")
}
}
}
func main() {
fmt.Println("=== Basic Channel ===")
ch := make(chan string)
go sender(ch)
for message := range ch {
fmt.Println("Received:", message)
}
fmt.Println("\n=== Buffered Channel ===")
bufferedChannelExample()
fmt.Println("\n=== Select Statement ===")
selectExample()
}
Error Handling
package main
import (
"errors"
"fmt"
"os"
)
// Custom error type
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("Validation error in %s: %s", e.Field, e.Message)
}
// Function that returns error
func validateAge(age int) error {
if age < 0 {
return ValidationError{
Field: "age",
Message: "age must be non-negative",
}
}
if age > 150 {
return ValidationError{
Field: "age",
Message: "age must be 150 or less",
}
}
return nil
}
// Error handling in file operations
func readFile(filename string) (string, error) {
content, err := os.ReadFile(filename)
if err != nil {
return "", fmt.Errorf("file read error: %w", err)
}
return string(content), nil
}
// panic and recover
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Panic recovered: %v\n", r)
}
}()
fmt.Println("Executing risky operation...")
panic("something went wrong!")
fmt.Println("This line won't be executed")
}
func main() {
// Error handling examples
ages := []int{25, -5, 200, 30}
for _, age := range ages {
if err := validateAge(age); err != nil {
fmt.Printf("Error - Age %d: %v\n", age, err)
// Type assertion to check custom error
if ve, ok := err.(ValidationError); ok {
fmt.Printf(" Field: %s\n", ve.Field)
}
} else {
fmt.Printf("Age %d is valid\n", age)
}
}
// File read error example
_, err := readFile("nonexistent.txt")
if err != nil {
fmt.Printf("File error: %v\n", err)
}
// panic/recover example
fmt.Println("\n=== Panic/Recover ===")
riskyFunction()
fmt.Println("Main processing continues")
}
Versions
Version | Release Date | Major Features |
---|---|---|
Go 1.23 | 2024-08 | Range-over-func, Timer reset behavior |
Go 1.22 | 2024-02 | For-range over integers, Math/rand v2 |
Go 1.21 | 2023-08 | Built-in functions min/max/clear, WASM |
Go 1.20 | 2023-02 | Comparable types, Context improvements |
Go 1.19 | 2022-08 | Generics improvements, Doc comments |
Go 1.18 | 2022-03 | Generics, Fuzzing, Workspaces |
Go 1.17 | 2021-08 | Module graph pruning, Call stack traces |
Reference Links
Official Documentation
- Go Official Site - Official website
- Go Documentation - Official documentation
- A Tour of Go - Interactive Go tutorial
Learning Resources
- Go by Example - Learn Go with examples
- Effective Go - How to write effective Go
- Go Wiki - Detailed information about Go
Development Tools
- Go Packages - Go package documentation
- Go Playground - Try Go in your browser
- Awesome Go - Collection of Go libraries and tools