Update tech_docs/go_getting_started.md

This commit is contained in:
2024-06-27 06:37:31 +00:00
parent 9fe4341754
commit bf6c0b9a6c

View File

@@ -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: