From bf6c0b9a6c18a3c22c53d70fda832f1452dcbde5 Mon Sep 17 00:00:00 2001 From: medusa Date: Thu, 27 Jun 2024 06:37:31 +0000 Subject: [PATCH] Update tech_docs/go_getting_started.md --- tech_docs/go_getting_started.md | 786 ++++++++++++++++++++++++++++++++ 1 file changed, 786 insertions(+) diff --git a/tech_docs/go_getting_started.md b/tech_docs/go_getting_started.md index 10d5c1d..fa82af9 100644 --- a/tech_docs/go_getting_started.md +++ b/tech_docs/go_getting_started.md @@ -1,3 +1,789 @@ +### Stage 0: Core Concepts in Golang + +--- + +#### Overview + +This stage covers the fundamental data structures in Golang: slices, maps, arrays, and structs. It provides a detailed comparison to help you decide which data structure to use based on the nature of your data and the operations you need to perform. + +--- + +### 1. Slices + +#### Characteristics + +- **Dynamic Size**: Slices are dynamically-sized, unlike arrays. +- **Backed by Arrays**: Slices are backed by arrays and provide a view into them. +- **Reslicing**: You can slice slices, creating new slices that share the same underlying array. + +#### Use Cases + +- **Dynamic Arrays**: When you need a dynamic array with convenient operations. +- **Subsequences**: When you need to work with subsequences of an array. + +#### Example: Storing a List of Names + +```go +names := []string{"Alice", "Bob", "Charlie"} + +// Accessing elements +secondName := names[1] // Bob + +// Adding an element +names = append(names, "David") + +// Slicing +subset := names[1:3] // {"Bob", "Charlie"} +``` + +--- + +### 2. Maps + +#### Characteristics + +- **Key-Value Pairs**: Maps store data in key-value pairs. +- **Unordered**: The order of map entries is not guaranteed. +- **Dynamic Size**: Maps can grow and shrink as needed. + +#### Use Cases + +- **Associative Arrays**: When you need to associate keys with values. +- **Fast Lookups**: When you need fast lookups by key. + +#### Example: Storing Product Prices + +```go +prices := map[string]float64{ + "Apple": 1.99, + "Banana": 0.49, + "Cherry": 2.99, +} + +// Accessing elements +applePrice := prices["Apple"] + +// Adding an element +prices["Date"] = 3.49 + +// Deleting an element +delete(prices, "Banana") +``` + +--- + +### 3. Arrays + +#### Characteristics + +- **Fixed Size**: Arrays have a fixed size defined at compile time. +- **Value Type**: Arrays are value types, meaning they are copied on assignment. +- **Performance**: Useful for performance-critical code where size is known. + +#### Use Cases + +- **Fixed-Size Collections**: When you know the size of the collection in advance. +- **Performance-Critical**: When performance is a concern and you need a fixed-size array. + +#### Example: Storing Scores + +```go +var scores [5]int + +// Assigning values +scores[0] = 100 +scores[1] = 90 + +// Iterating over an array +for i, score := range scores { + fmt.Println(i, score) +} +``` + +--- + +### 4. Structs + +#### Characteristics + +- **Custom Data Types**: Structs allow you to create custom data types. +- **Named Fields**: Fields are accessed by name. +- **Composition**: Structs can be composed of other structs. + +#### Use Cases + +- **Complex Data Structures**: When you need to model complex data structures. +- **Grouping Data**: When you need to group related data together. + +#### Example: Defining a Person + +```go +type Person struct { + Name string + Age int +} + +person := Person{Name: "Alice", Age: 30} + +// Accessing fields +name := person.Name + +// Modifying fields +person.Age = 31 +``` + +--- + +### Detailed Comparison + +| Feature | Slice | Map | Array | Struct | +|------------------|--------------------------------|--------------------------|--------------------------|---------------------------| +| **Size** | Dynamic | Dynamic | Fixed | N/A | +| **Indexing** | Integer | Key | Integer | Field | +| **Mutability** | Mutable | Mutable | Mutable | Mutable | +| **Uniqueness** | Allows duplicates | Unique keys | Allows duplicates | N/A | +| **Use Case** | Dynamic arrays, subsequences | Associative arrays | Fixed-size collections | Complex data structures | + +--- + +### Summary of Core Concepts + +1. **Slices**: Use for dynamic arrays and subsequences. +2. **Maps**: Use for associative arrays and fast lookups. +3. **Arrays**: Use for fixed-size collections and performance-critical code. +4. **Structs**: Use for complex data structures and grouping related data. + +By mastering these core concepts, you'll be well-equipped to handle a wide range of programming challenges efficiently in Golang. + +--- + +### Stage 1: Intermediate Concepts in Golang + +Building on the core concepts from Stage 0, Stage 1 delves deeper into more advanced techniques, optimizations, and specialized data structures. + +--- + +#### 1. **Advanced Slice Techniques** + +- **Capacity Management**: Understanding and managing slice capacity. + ```go + numbers := make([]int, 0, 10) // len(numbers) == 0, cap(numbers) == 10 + ``` + +- **Copying Slices**: Efficiently copying slices. + ```go + src := []int{1, 2, 3} + dst := make([]int, len(src)) + copy(dst, src) + ``` + +- **Appending Slices**: Using `append()` function efficiently. + ```go + s1 := []int{1, 2} + s2 := []int{3, 4} + s1 = append(s1, s2...) // {1, 2, 3, 4} + ``` + +--- + +#### 2. **Advanced Map Techniques** + +- **Concurrent Maps**: Using `sync.Map` for concurrent access. + ```go + var m sync.Map + m.Store("key", "value") + value, ok := m.Load("key") + ``` + +- **Zero Value Handling**: Checking if a map key exists. + ```go + value, exists := prices["Apple"] + ``` + +- **Map of Maps**: Nested maps for complex data structures. + ```go + nestedMap := map[string]map[string]int{ + "category1": {"item1": 1, "item2": 2}, + "category2": {"item3": 3}, + } + ``` + +--- + +#### 3. **Advanced Array Techniques** + +- **Multidimensional Arrays**: Working with 2D and 3D arrays. + ```go + var matrix [3][3]int + matrix[0][0] = 1 + ``` + +- **Array Slicing**: Creating slices from arrays. + ```go + array := [5]int{1, 2, 3, 4, 5} + slice := array[1:4] // {2, 3, 4} + ``` + +--- + +#### 4. **Advanced Struct Techniques** + +- **Embedding Structs**: Composing structs using embedding. + ```go + type Address struct { + Street string + City string + } + + type Person struct { + Name string + Age int + Address + } + + person := Person{Name: "Alice", Age: 30, Address: Address{Street: "Main St", City: "Wonderland"}} + ``` + +- **Tags and Reflection**: Using struct tags and reflection. + ```go + type User struct { + Name string `json:"name"` + Age int `json:"age"` + } + + u := User{Name: "Alice", Age: 30} + jsonData, _ := json.Marshal(u) + ``` + +--- + +### Summary of Intermediate Concepts + +1. **Slices**: Capacity management, copying, and appending. +2. **Maps**: Concurrent access, zero value handling, and nested maps. +3. **Arrays**: Multidimensional arrays and array slicing. +4. **Structs**: Embedding, tags, and reflection. + +By mastering these intermediate concepts, you'll be able to handle more complex data structures and write optimized, high-performance Golang code. + +--- + +### Stage 2: Advanced Concepts in Golang + +At this stage, you'll delve into more specialized data structures, optimization strategies, and concurrent programming techniques essential for handling complex problems efficiently. + +--- + +#### 1. **Custom Data Structures** + +- **Linked Lists**: Implementing and using linked lists. + ```go + type Node struct { + Value int + Next *Node + } + + type LinkedList struct { + Head *Node + } + + func (ll *LinkedList) Append(value int) { + newNode := &Node{Value: value} + if ll.Head == nil { + ll.Head = newNode + } else { + current := ll.Head + for current.Next != nil { + current = current.Next + } + current.Next = newNode + } + } + ``` + +- **Trees**: Implementing binary search trees and AVL trees. + ```go + type TreeNode struct { + Value int + Left *TreeNode + Right *TreeNode + } + + func insertNode(root *TreeNode, value int) *TreeNode { + if root == nil { + return &TreeNode{Value: value} + } + if value < root.Value { + root.Left = insertNode(root.Left, value) + } else { + root.Right = insertNode(root.Right, value) + } + return root + } + ``` + +- **Graphs**: Representing and manipulating graphs. + ```go + type Graph struct { + nodes map[int][] + +int + } + + func (g *Graph) AddEdge(u, v int) { + if g.nodes == nil { + g.nodes = make(map[int][]int) + } + g.nodes[u] = append(g.nodes[u], v) + } + ``` + +--- + +#### 2. **Concurrent Programming** + +- **Goroutines and Channels**: Using goroutines and channels for concurrency. + ```go + func worker(id int, jobs <-chan int, results chan<- int) { + for j := range jobs { + fmt.Println("worker", id, "started job", j) + time.Sleep(time.Second) + fmt.Println("worker", id, "finished job", j) + results <- j * 2 + } + } + + func main() { + jobs := make(chan int, 100) + results := make(chan int, 100) + + for w := 1; w <= 3; w++ { + go worker(w, jobs, results) + } + + for j := 1; j <= 5; j++ { + jobs <- j + } + close(jobs) + + for a := 1; a <= 5; a++ { + <-results + } + } + ``` + +- **Sync Package**: Using `sync.Mutex`, `sync.WaitGroup`, and `sync.Once`. + ```go + var mu sync.Mutex + var count int + + func increment() { + mu.Lock() + count++ + mu.Unlock() + } + + func main() { + var wg sync.WaitGroup + + for i := 0; i < 1000; i++ { + wg.Add(1) + go func() { + defer wg.Done() + increment() + }() + } + + wg.Wait() + fmt.Println("Final count:", count) + } + ``` + +--- + +#### 3. **Performance Optimization** + +- **Profiling and Benchmarking**: Using `pprof` and `testing` packages for profiling and benchmarking. + ```go + import ( + "testing" + ) + + func BenchmarkMyFunction(b *testing.B) { + for i := 0; i < b.N; i++ { + MyFunction() + } + } + ``` + +- **Memory Management**: Understanding and optimizing memory usage. + ```go + import ( + "runtime" + ) + + func printMemUsage() { + var m runtime.MemStats + runtime.ReadMemStats(&m) + fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc)) + fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc)) + fmt.Printf("\tSys = %v MiB", bToMb(m.Sys)) + fmt.Printf("\tNumGC = %v\n", m.NumGC) + } + + func bToMb(b uint64) uint64 { + return b / 1024 / 1024 + } + ``` + +--- + +### Summary of Advanced Concepts + +1. **Custom Data Structures**: Designing and implementing linked lists, trees, and graphs. +2. **Concurrent Programming**: Using goroutines, channels, and the sync package for concurrency. +3. **Performance Optimization**: Profiling, benchmarking, and memory management. + +By mastering these advanced concepts, you'll be equipped to tackle complex programming challenges, design efficient solutions, and optimize performance at scale, solidifying your expertise as a Golang developer. + +--- + +### Stage 2.5: Subject Matter Expert (SME) Level in Golang + +At this level, focus on mastering complex data structures, optimization strategies, and integrating data structures with algorithms. This includes designing custom data structures and optimizing performance at scale. + +--- + +#### 1. **Custom Data Structures** + +- **Complex Data Structures**: Designing advanced data structures such as heaps, tries, and disjoint-set data structures. + ```go + type MinHeap struct { + array []int + } + + func (h *MinHeap) Insert(key int) { + h.array = append(h.array, key) + h.heapifyUp(len(h.array) - 1) + } + + func (h *MinHeap) heapifyUp(index int) { + for h.array[parent(index)] > h.array[index] { + h.swap(parent(index), index) + index = parent(index) + } + } + + func parent(i int) int { + return (i - 1) / 2 + } + + func (h *MinHeap) swap(i1, i2 int) { + h.array[i1], h.array[i2] = h.array[i2], h.array[i1] + } + ``` + +- **Balanced Trees**: Implementing AVL trees, Red-Black trees, and B-trees. + ```go + type AVLNode struct { + key int + height int + left *AVLNode + right *AVLNode + } + + func (n *AVLNode) height() int { + if n == nil { + return 0 + } + return n.height + } + + func max(a, b int) int { + if a > b { + return a + } + return b + } + + func rightRotate(y *AVLNode) *AVLNode { + x := y.left + T2 := x.right + + x.right = y + y.left = T2 + + y.height = max(y.left.height(), y.right.height()) + 1 + x.height = max(x.left.height(), x.right.height()) + 1 + + return x + } + + func leftRotate(x *AVLNode) *AVLNode { + y := x.right + T2 := y.left + + y.left = x + x.right = T2 + + x.height = max(x.left.height(), x.right.height()) + 1 + y.height = max(y.left.height(), y.right.height()) + 1 + + return y + } + + func insert(root *AVLNode, key int) *AVLNode { + if root == nil { + return &AVLNode{key: key, height: 1} + } + + if key < root.key { + root.left = insert(root.left, key) + } else if key > root.key { + root.right = insert(root.right, key) + } else { + return root + } + + root.height = 1 + max(root.left.height(), root.right.height()) + + balance := root.left.height() - root.right.height() + + if balance > 1 && key < root.left.key { + return rightRotate(root) + } + if balance < -1 && key > root.right.key { + return leftRotate(root) + } + if balance > 1 && key > root.left.key { + root.left = leftRotate(root.left) + return rightRotate(root) + } + if balance < -1 && key < root.right.key { + root.right = rightRotate(root.right) + return leftRotate(root) + } + + return root + } + ``` + +- **Graphs**: Implementing advanced graph algorithms such as Dijkstra's and A*. + ```go + type Edge struct { + node int + weight int + } + + type Graph struct { + nodes map[int][]Edge + } + + func (g *Graph) AddEdge(u, v, weight int) { + g.nodes[u] = append(g.nodes[u], Edge{node: v, weight: weight}) + } + + func (g *Graph) Dijkstra(start int) map[int]int { + dist := make(map[int]int) + for node := range g.nodes { + dist[node] = int(^uint(0) >> 1) // Initialize with infinity + } + dist[start] = 0 + + pq := &MinHeap{} + pq.Insert(start) + + for len(pq.array) > 0 { + current := pq.ExtractMin() + + for _, edge := range g.nodes[current] { + alt := dist[current] + edge.weight + if alt < dist[edge.node] { + dist[edge.node] = alt + pq.Insert(edge.node) + } + } + } + + return dist + } + + func (h *MinHeap) ExtractMin() int { + if len(h.array) == 0 { + return -1 + } + + root := h.array[0] + h.array[0] = h.array[len(h.array)-1] + h.array = h.array[:len(h.array)-1] + + h.heapifyDown(0) + + return root + } + + func (h *MinHeap) heapifyDown(index int) { + lastIndex := len(h.array) - 1 + l, r := left(index), right(index) + childToCompare := 0 + + for l <= lastIndex { + if l == lastIndex || h.array[l] < h.array[r] { + childToCompare = l + } else { + childToCompare = r + } + + if h.array[index] > h.array[childToCompare] { + h.swap(index, childToCompare) + index = childToCompare + l, r = left(index), right(index) + } else { + return + } + } + } + + func left(i int) int { + return 2*i + 1 + } + + func right(i int) int { + return 2*i + 2 + } + ``` + +--- + +#### 2. **Advanced Algorithms** + +- **Algorithm Integration**: Combining data structures with algorithms for problem-solving. + ```go + func quicksort(arr []int) []int { + if len(arr) < 2 { + return arr + } + + left, right := 0, len(arr)-1 + + pivot := + + rand.Int() % len(arr) + + arr[pivot], arr[right] = arr[right], arr[pivot] + + for i := range arr { + if arr[i] < arr[right] { + arr[i], arr[left] = arr[left], arr[i] + left++ + } + } + + arr[left], arr[right] = arr[right], arr[left] + + quicksort(arr[:left]) + quicksort(arr[left+1:]) + + return arr + } + ``` + +- **Dynamic Programming**: Using slices and maps for memoization and tabulation. + ```go + func fibonacci(n int, memo map[int]int) int { + if n <= 1 { + return n + } + if _, ok := memo[n]; !ok { + memo[n] = fibonacci(n-1, memo) + fibonacci(n-2, memo) + } + return memo[n] + } + ``` + +--- + +#### 3. **Performance Engineering** + +- **Profiling and Optimization**: Using `pprof` and `testing` packages for profiling and benchmarking. + ```go + import ( + "testing" + ) + + func BenchmarkMyFunction(b *testing.B) { + for i := 0; i < b.N; i++ { + MyFunction() + } + } + ``` + +- **Concurrency and Parallelism**: Leveraging `sync`, `atomic`, and `context` packages for concurrency. + ```go + import ( + "sync" + "sync/atomic" + ) + + var count int64 + + func increment() { + atomic.AddInt64(&count, 1) + } + + func main() { + var wg sync.WaitGroup + + for i := 0; i < 1000; i++ { + wg.Add(1) + go func() { + defer wg.Done() + increment() + }() + } + + wg.Wait() + fmt.Println("Final count:", count) + } + ``` + +- **Big Data and Scalability**: Techniques for handling and processing large datasets efficiently. + ```go + import ( + "bufio" + "os" + ) + + func processLargeFile(filePath string) { + file, err := os.Open(filePath) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + // Process each line + } + + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + } + ``` + +--- + +### Summary of SME Level Concepts + +1. **Custom Data Structures**: Designing and implementing complex data structures like heaps, tries, and balanced trees. +2. **Advanced Algorithms**: Integrating data structures with advanced algorithms and dynamic programming techniques. +3. **Performance Engineering**: Profiling, concurrency, parallelism, and scalability techniques. + +By mastering these SME level concepts, you'll be equipped to tackle the most complex programming challenges, design efficient solutions, and optimize performance at scale, solidifying your expertise as a Golang developer. + +--- + Certainly! Here's a comprehensive overview of the `select` statement in Go: 1. Introduction: