🗓️ 26102024 1430
Core Concept: Go is a statically-typed, compiled language designed for simplicity and concurrency, using structs instead of classes and composition instead of inheritance.
Core Features
- Compiled to single binary
- Statically typed with type inference
- Garbage collected
- Built-in concurrency (goroutines)
- Simple syntax, fast compilation
Basic Syntax
Variables
var name string = "John"
name := "John" // short declaration (inside functions)
age := 25 // type inferred
Functions
func add(a, b int) int {
return a + b
}
// Multiple returns
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("divide by zero")
}
return a / b, nil
}
Structs (not classes)
type User struct {
Name string // exported (capitalized = public)
age int // unexported (lowercase = private)
}
// Constructor by convention
func NewUser(name string, age int) *User {
return &User{Name: name, age: age}
}
Methods (attached to types)
func (u *User) IsAdult() bool {
return u.age >= 18
}
// Pointer receiver (*User) allows mutation
// Value receiver (User) receives a copy
Interfaces (implicit)
type Writer interface {
Write(data []byte) error
}
// Any type with Write() method implements Writer
// No "implements" keyword needed
Error Handling
// Errors are values, not exceptions
result, err := mightFail()
if err != nil {
return err // or handle it
}
// use result
No try/catch. Check errors explicitly.
Key Concepts
Pointers
x := 42
p := &x // p is pointer to x
*p = 21 // dereference and modify
fmt.Println(x) // prints 21
Slices (dynamic arrays)
nums := []int{1, 2, 3}
nums = append(nums, 4)
for i, n := range nums {
fmt.Println(i, n)
}
Maps
m := make(map[string]int)
m["age"] = 25
value, exists := m["age"]
Goroutines (lightweight threads)
go doWork() // runs concurrently
// With channels
ch := make(chan string)
go func() {
ch <- "result" // send
}()
msg := <-ch // receive
See go_concurrency_model for details.
Defer
func readFile() error {
file, err := os.Open("file.txt")
if err != nil {
return err
}
defer file.Close() // runs when function exits
// do work with file
}
Project Structure
project/
├── cmd/api/ # main.go (entry point)
├── internal/ # private code (can't be imported externally)
│ ├── handlers/
│ ├── services/
│ ├── models/
│ └── database/
├── go.mod # dependencies
└── go.sum # checksums
Package Management
go mod init github.com/user/project # initialize
go get package # add dependency
go mod tidy # clean up
go mod download # fetch deps
go.mod example:
module github.com/user/project
require (
github.com/go-chi/chi/v5 v5.0.11
)
Common Patterns
Constructor pattern
type Service struct {
db Database
}
func NewService(db Database) *Service {
return &Service{db: db}
}
Error wrapping
if err != nil {
return fmt.Errorf("failed to save: %w", err)
}
Options pattern
type Option func(*Config)
func WithTimeout(t time.Duration) Option {
return func(c *Config) {
c.Timeout = t
}
}
func NewClient(opts ...Option) *Client {
c := &Client{}
for _, opt := range opts {
opt(&c.config)
}
return c
}
Important Rules
- Capitalization = visibility:
Name(public),name(private) - No inheritance: Use composition and interfaces
- Errors are values: Handle explicitly, no exceptions
- Pointers for mutation: Value receivers copy, pointer receivers mutate
- Defer stacks: Multiple defers execute in LIFO order
TIP
Go prefers explicit code over clever abstractions. "Clear is better than clever."
Quick Reference
// Control flow
if x > 0 {
// ...
}
for i := 0; i < 10; i++ {
// ...
}
for key, value := range map {
// ...
}
switch x {
case 1:
// ...
default:
// ...
}
// Type assertion
value, ok := interface{}.(Type)
// Type switch
switch v := i.(type) {
case int:
// v is int
case string:
// v is string
}
Related Concepts
- go_concurrency_model - Goroutines and scheduling
- go_interfaces - Interface patterns
- go_error_handling - Error patterns
- go_testing - Testing in Go
- go_modules - Dependency management
References
- Tour of Go - Interactive tutorial
- Effective Go - Best practices
- Go by Example - Code examples