- Concurrency: Multiple tasks start, run, and complete in overlapping time periods.
- Example: Single-core CPU running multiple goroutines by switching context.
- Parallelism: Multiple tasks run at exactly the same time using multiple CPU cores.
- Example: On a quad-core CPU, four goroutines can truly run in parallel.
Go (Golang) is an open-source, statically typed, compiled programming language created at Google.
Used for: High-performance backend services, Cloud-native applications, Microservices, Concurrency-heavy systems, CLI tools, DevOps tools.
Why popular: Extremely fast compilation, Built-in concurrency (goroutines & channels), Simple syntax, No inheritance complexity, Excellent standard library.
Tip: Go is ideal for distributed systems and scalable cloud architecture.
Using:
go func() { fmt.Println("Running in goroutine")
}()</code></pre>
Go uses explicit error return values, not exceptions.
val, err := someFunc()if err != nil {
return err
}</code></pre>
Advanced: Use fmt.Errorf() with %w for wrapping, and errors.Is()/errors.As() for checking types.
Interfaces are implicitly implemented. If a type provides the methods derived in the interface, it implements it (Duck Typing).
type Animal interface { Speak() string
}
// Dog implicitly implements Animal by having Speak()
func (Dog) Speak() string { return "Woof" }</code></pre>
Tools: go test -bench ., pprof (profiling), go build -gcflags "-m" (escape analysis).
Static: Explicit type declaration.
var age int = 10Dynamic (Inference): Type inferred from value.
age := 10
Using fmt.Scan (space-separated) or bufio (buffered IO).
var name stringvar age int
fmt.Scan(&name, &age)</code></pre>
Check values immediately after reading.
if age < 0 { fmt.Println("Invalid age")
}</code></pre>
for { fmt.Print("Enter age: ")
fmt.Scan(&age)
if age > 0 { break }
}</code></pre>
Use os.Args for raw arguments, flag for parsing flags, or libraries like Cobra/Viper for robust tools.
name := flag.String("name", "Guest", "User name")flag.Parse()
fmt.Println("Hello", *name)</code></pre>
The flag package parses command-line arguments like --port=8080.
port := flag.String("port", "8000", "Server port")flag.Parse()
fmt.Printf("Starting on %s\n", *port)</code></pre>
Cobra is the standard for modern Go CLIs (used by Kubernetes, Docker). It manages commands, subcommands, and flags.
Viper handles configuration management (JSON/YAML files, env vars).
Enhance UX using libraries:
Use json.MarshalIndent for pretty-printing data to storage.
data, _ := json.MarshalIndent(users, "", " ")os.WriteFile("users.json", data, 0644)</code></pre>
Flow: Read File -> Unmarshal to Struct Slice -> Modify Slice (Append/Delete) -> Marshal -> Write Back.
Use the database driver to connect.
import _ "github.com/go-sql-driver/mysql"db, _ := sql.Open("mysql", "user:pass@/dbname")</code></pre>
State management in CLI: Variables hold the "logged in" state (token/user struct). The main loop renders different options based on this state.
Run background tasks without blocking the UI/Input loop.
go func() { performBackgroundSync()
}()
// Main CLI loop continues here...</code></pre>
Goroutine: Managed by Go runtime, starts with small stack (2KB), grows dynamically, multiplexed onto OS threads.
Thread: Managed by OS, fixed large stack (1MB+), expensive context switch.
Typed conduits for synchronization and data transfer between goroutines.
ch := make(chan int)go func() { ch <- 10 }() // Send
val := <-ch // Receive</code></pre>
Unbuffered: make(chan int). Synchronous. Sender blocks until Receiver performs receive.
Buffered: make(chan int, 3). Asynchronous until buffer is full. Sender only blocks if buffer is full.
Like a switch for channels. Blocks until one of its cases (send/receive) can proceed. Used for handling timeouts or multiple data sources.
It uses a concurrent, tri-color mark-and-sweep algorithm. It is optimized for low latency (short stop-the-world pauses) rather than raw throughput.
Array: Fixed length, value type (copying copies entire array).
Slice: Dynamic length, reference type (pointer to underlying array).
Maps are not safe for concurrent use. Use sync.Mutex to lock before access, or use sync.Map for specific high-concurrency read-heavy cases.
Go favors Composition. Embedding a struct allows utilizing its methods, but it's not "is-a" relationship, it's "has-a" with syntax sugar.
type Car struct { Engine } // Car promotes methods of Engine
go mod init creates a new module. go.mod tracks dependencies and versions, replacing the old GOPATH system.
Schedules a function call to be run after the surrounding function returns. Executed in LIFO order. Common for cleanup (closing files, unlocking mutexes).
Panic: Stops normal execution, unwinds stack, runs deferred functions. Used for unrecoverable errors.
Recover: Regains control of a panicking goroutine. Only works inside defer.
The CPU reads data in word-sized chunks. Go struct fields are aligned to these boundaries. Proper ordering of struct fields (largest to smallest) can save memory by reducing padding.
Used to carry deadlines, cancellation signals, and request-scoped values across API boundaries and between processes.
Determines if variables should be on stack or heap. Heap allocation causes GC pressure. Optimization: Keep variables on stack (don't return pointers to local vars if not needed) to reduce GC overhead.
Use golang.org/x/time/rate.Limiter or a Token Bucket implementation. Call Wait(ctx) before making a request.
