Click any item to expand the explanation and examples.
📝 Basics
Variables and types basics
// Declare and assign var name string = "Alice" var age int = 30// Short declaration (most common) name := “Alice” age := 30 active := true
// Multiple x, y := 10, 20
// Constants const Pi = 3.14159 const ( StatusOK = 200 StatusError = 500 )
// Basic types // string, bool // int, int8, int16, int32, int64 // uint, uint8 (byte), uint16, uint32, uint64 // float32, float64 // complex64, complex128
// Zero values (defaults) // int → 0, float → 0.0, string → "", bool → false, pointer → nil
Functions basics
// Basic function
func greet(name string) string {
return "Hello, " + name
}
// Multiple return values
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf(“division by zero”)
}
return a / b, nil
}
result, err := divide(10, 3)
// Named return values
func swap(a, b int) (x, y int) {
x = b
y = a
return // naked return
}
// Variadic function
func sum(nums …int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
sum(1, 2, 3, 4)
// Anonymous function / closure
double := func(x int) int { return x * 2 }
double(5) // 10
📦 Data Structures
Slices data
// Create
nums := []int{1, 2, 3, 4, 5}
names := make([]string, 0, 10) // len=0, cap=10
// Append
nums = append(nums, 6)
nums = append(nums, 7, 8, 9)
// Slice
sub := nums[1:3] // [2, 3]
first3 := nums[:3] // [1, 2, 3]
last2 := nums[3:] // [4, 5]
// Length and capacity
len(nums)
cap(nums)
// Iterate
for i, v := range nums {
fmt.Println(i, v)
}
// Copy
dst := make([]int, len(nums))
copy(dst, nums)
// Delete element at index i
nums = append(nums[:i], nums[i+1:]…)
// Contains (no built-in — use slices package in Go 1.21+)
import “slices”
slices.Contains(nums, 3)
Maps data
// Create
ages := map[string]int{
"Alice": 30,
"Bob": 25,
}
// Or with make
ages := make(map[string]int)
// Set
ages[“Carol”] = 28
// Get (returns zero value if missing)
age := ages[“Alice”]
// Check if key exists
age, ok := ages[“Dave”]
if !ok {
fmt.Println(“Dave not found”)
}
// Delete
delete(ages, “Bob”)
// Iterate (order is random!)
for name, age := range ages {
fmt.Println(name, age)
}
// Length
len(ages)
Structs data
type User struct {
Name string
Email string
Age int
}
// Create
u := User{Name: “Alice”, Email: “alice@example.com”, Age: 30}
u := User{“Alice”, “alice@example.com”, 30} // positional
// Access
fmt.Println(u.Name)
u.Age = 31
// Pointer to struct
p := &User{Name: “Bob”}
p.Name = “Bob Updated” // Go auto-dereferences
// Methods
func (u User) FullName() string {
return u.Name
}
// Pointer receiver (can modify the struct)
func (u *User) SetEmail(email string) {
u.Email = email
}
// Embedding (composition)
type Admin struct {
User // Embedded — Admin “inherits” User fields
Level int
}
a := Admin{User: User{Name: “Alice”}, Level: 1}
a.Name // Works — promoted from User
🔌 Interfaces
Interfaces — implicit implementation interface
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
// Circle implements Shape (no “implements” keyword needed)
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// Use the interface
func printArea(s Shape) {
fmt.Printf(“Area: %.2f\n”, s.Area())
}
printArea(Circle{Radius: 5})
printArea(Rectangle{Width: 3, Height: 4})
// Empty interface (accepts anything)
func printAnything(v any) { // any = interface{}
fmt.Println(v)
}
// Type assertion
var s Shape = Circle{Radius: 5}
c, ok := s.(Circle)
if ok {
fmt.Println(c.Radius)
}
⚠️ Error Handling
Errors in Go errors
import (
"errors"
"fmt"
)
// Return errors
func findUser(id int) (*User, error) {
if id <= 0 {
return nil, fmt.Errorf(“invalid id: %d”, id)
}
return &User{Name: “Alice”}, nil
}
// Handle errors (the Go way)
user, err := findUser(1)
if err != nil {
log.Fatal(err)
}
// Custom error types
type NotFoundError struct {
ID int
}
func (e *NotFoundError) Error() string {
return fmt.Sprintf(“user %d not found”, e.ID)
}
// Wrap errors (Go 1.13+)
return fmt.Errorf(“fetching user: %w”, err)
// Check wrapped errors
if errors.Is(err, ErrNotFound) { }
var nfe *NotFoundError
if errors.As(err, &nfe) {
fmt.Println(nfe.ID)
}
⚡ Goroutines & Channels
Concurrency concurrency
// Start a goroutine go doWork()// Channel — communicate between goroutines ch := make(chan string)
go func() { ch <- “hello” // Send }()
msg := <-ch // Receive (blocks until value available)
// Buffered channel ch := make(chan int, 5) // Buffer size 5
// Range over channel go func() { for i := 0; i < 5; i++ { ch <- i } close(ch) }()
for v := range ch { fmt.Println(v) }
// Select — wait on multiple channels select { case msg := <-ch1: fmt.Println(msg) case msg := <-ch2: fmt.Println(msg) case <-time.After(5 * time.Second): fmt.Println(“timeout”) }
// WaitGroup — wait for goroutines to finish var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() fmt.Println(“Worker”, id) }(i) } wg.Wait()
🔧 Common Operations
Strings, JSON, HTTP stdlib
// Strings
import "strings"
strings.Contains("hello", "ell") // true
strings.HasPrefix("hello", "he") // true
strings.Split("a,b,c", ",") // ["a","b","c"]
strings.Join([]string{"a","b"}, "-") // "a-b"
strings.ToUpper("hello") // "HELLO"
strings.TrimSpace(" hi ") // "hi"
fmt.Sprintf("Hello %s, age %d", name, age)
// JSON
import “encoding/json”
// Struct to JSON
data, _ := json.Marshal(user)
// JSON to struct
json.Unmarshal(data, &user)
// HTTP server
http.HandleFunc(”/”, func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, “Hello!”)
})
http.ListenAndServe(“:8080”, nil)
// HTTP client
resp, err := http.Get(“https://api.example.com/users”)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
CLI commands cli
# Initialize module go mod init github.com/user/projectAdd dependencies
go get github.com/gin-gonic/gin
Tidy (remove unused, add missing)
go mod tidy
Run
go run main.go go run .
Build
go build -o myapp .
Test
go test ./… go test -v ./… go test -cover ./…
Format
go fmt ./…
Vet (find bugs)
go vet ./…