From e5b4830c8cab8c2c24ed69c2ec3baf8663a4da46 Mon Sep 17 00:00:00 2001 From: Archit Mishra Date: Thu, 4 Sep 2025 20:57:20 +0530 Subject: [PATCH] Add new cheatsheet for Go --- Languages/README.md | 1 + Languages/golang.md | 1641 +++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + resources.html | 1 + 4 files changed, 1644 insertions(+) create mode 100644 Languages/golang.md diff --git a/Languages/README.md b/Languages/README.md index 17ff682..6e2eae6 100644 --- a/Languages/README.md +++ b/Languages/README.md @@ -3,3 +3,4 @@ - [Typescript](Typescript.md) - [Python](python.md) - [Javascript](Javascript.md) +- [Golang](golang.md) \ No newline at end of file diff --git a/Languages/golang.md b/Languages/golang.md new file mode 100644 index 0000000..ff3a6a9 --- /dev/null +++ b/Languages/golang.md @@ -0,0 +1,1641 @@ +# Go Programming Language Tutorial + +## Table of Contents + +- [What is Go?](#what-is-go) +- [Why Go?](#why-go) +- [Installation](#installation) +- [Hello, World!](#hello-world) +- [Basic Syntax](#basic-syntax) +- [Variables and Constants](#variables-and-constants) +- [Data Types](#data-types) +- [Operators](#operators) +- [Control Flow](#control-flow) +- [Functions](#functions) +- [Arrays and Slices](#arrays-and-slices) +- [Maps](#maps) +- [Structs](#structs) +- [Interfaces](#interfaces) +- [Pointers](#pointers) +- [Error Handling](#error-handling) +- [Goroutines and Channels](#goroutines-and-channels) +- [Packages and Modules](#packages-and-modules) +- [Testing](#testing) +- [Intermediate Go](#intermediate-go) +- [Tutorials](#tutorials) + +## What is Go? + +Go (also known as Golang) is a statically typed, compiled programming language developed at Google in 2009. It was created by some of the most legendary figures in Computer Science: + +1. **[Ken Thompson](https://www.invent.org/inductees/ken-thompson)** + - Co-creator of Unix Operating System with Dennis Ritchie + - Creator of B Programming Language (predecessor to C) + - Co-inventor of UTF-8 encoding + - Turing Award winner (1983) + +2. **[Rob Pike](https://en.wikipedia.org/wiki/Rob_Pike)** + - Co-creator of UTF-8 and Plan 9 + - Built the first window system for Unix + - Created Newsqueak (predecessor to Go's concurrency model) + +3. **[Robert Griesemer](https://en.wikipedia.org/wiki/Robert_Griesemer)** + - Worked on Chrome V8 JavaScript Engine + - Creator of Java HotSpot virtual machine + - Creator of Sawzall (Google's data-processing language) + +## Why Go? + +Go was designed with simplicity and efficiency in mind: + +- **Simple syntax** with only 25 reserved keywords +- **Fast compilation** times +- **Built-in concurrency** support with goroutines +- **Garbage collection** for memory management +- **Strong typing** with type inference +- **Cross-platform** compilation +- **Excellent standard library** + +Go is primarily used for: +- Web servers and APIs +- Cloud and network services +- DevOps and system administration tools +- Microservices +- Command-line tools +- Distributed systems + +### Some famous Products built using Go - +- Docker +- Kubernetes +- CockroachDB +- Terraform +- Prometheus +- Gitea +- fzf + +## Installation + +### Download and Install +- Visit [golang.org](https://golang.org/dl/) and download the installer for your operating system +- Follow the installation instructions for your platform +- Verify installation by running `go version` in your terminal + +### Setting up GOPATH (Optional for Go 1.11+) +```bash +export GOPATH=$HOME/go +export PATH=$PATH:$GOPATH/bin +``` + +## Hello, World! + +Create a new file `hello.go`: + +```go +package main + +import "fmt" + +func main() { + fmt.Println("Hello, World!") +} +``` + +Run the program: +```bash +go run hello.go +``` + +## Basic Syntax + +### Setting Up Project - +Run `go mod` with the name of the project in the directory. (Directory is not created, just files are initialized). +```go +go mod init +``` +>Note: It'll create a `god.mod` +file. + +### Package Declaration +Every Go file starts with a package declaration: +```go +package main +``` + +### Import Statements +```go +import "fmt" +import "math" + +// Or multiple imports +import ( + "fmt" + "math" +) +``` + +### Comments +```go +// Single line comment + +/* +Multi-line +comment +*/ +``` + +## Variables and Constants + +### Variable Declaration +Variables can be declared in either of two ways- +- With explicit type declaration , which is something like this - `var ` + + ```go + // Explicit type declaration + var name string = "John" + var age int = 30 + + // Type inference + var name = "John" + var age = 30 + ``` +- Short hand variable declaration using `:=` - + + ```go + // Short variable declaration (inside functions only) + name := "John" + age := 30 + + // Multiple variables + var a, b, c int = 1, 2, 3 + x, y := 10, 20 + ``` +--- +### Constants +```go +const PI = 3.14159 +const ( + StatusOK = 200 + StatusNotFound = 404 +) +``` +--- +### Zero Values +Variables declared without explicit initial value are given zero values: + +```go +var i int // 0 +var f float64 // 0.0 +var b bool // false +var s string // "" +``` +## Data Types + +### Basic Types + +```go +// Integers +var i8 int8 = 127 +var i16 int16 = 32767 +var i32 int32 = 2147483647 +var i64 int64 = 9223372036854775807 +var ui uint = 42 + +// Floating point +var f32 float32 = 3.14 +var f64 float64 = 3.141592653589793 + +// Boolean +var isActive bool = true + +// String +var message string = "Hello, Go!" + +// Byte (alias for uint8) +var b byte = 255 + +// Rune (alias for int32, represents Unicode code point) +var r rune = 'A' +``` +> `rune` in Go is like `char` in C. + +### Type Conversion +```go +var i int = 42 +var f float64 = float64(i) +var u uint = uint(f) +``` + +## Operators + +### Arithmetic Operators +```go +a := 10 +b := 3 + +sum := a + b // Addition: 13 +diff := a - b // Subtraction: 7 +product := a * b // Multiplication: 30 +quotient := a / b // Division: 3 +remainder := a % b // Modulus: 1 +``` + +### Comparison Operators +```go +a := 10 +b := 5 + +equal := a == b // false +notEqual := a != b // true +greater := a > b // true +less := a < b // false +greaterEq := a >= b // true +lessEq := a <= b // false +``` + +### Logical Operators +```go +a := true +b := false + +and := a && b // false +or := a || b // true +not := !a // false +``` + +### Assignment Operators +```go +x := 10 +x += 5 // x = x + 5 +x -= 3 // x = x - 3 +x *= 2 // x = x * 2 +x /= 4 // x = x / 4 +x %= 3 // x = x % 3 +```## Cont +rol Flow + +### If Statements +```go +age := 18 + +if age >= 18 { + fmt.Println("Adult") +} else if age >= 13 { + fmt.Println("Teenager") +} else { + fmt.Println("Child") +} + +// If with short statement +if x := 10; x > 5 { + fmt.Println("x is greater than 5") +} +``` + +### Switch Statements +```go +day := "Monday" + +switch day { +case "Monday": + fmt.Println("Start of work week") +case "Friday": + fmt.Println("TGIF!") +case "Saturday", "Sunday": + fmt.Println("Weekend!") +default: + fmt.Println("Midweek") +} + +// Switch without expression (like if-else chain) +score := 85 +switch { +case score >= 90: + fmt.Println("A") +case score >= 80: + fmt.Println("B") +case score >= 70: + fmt.Println("C") +default: + fmt.Println("F") +} +``` + +### Loops + +There's no while loop in go. +#### For Loop +```go +// Traditional for loop +for i := 0; i < 5; i++ { + fmt.Println(i) +} + +// There are no while loop in Golang +// While-like loop +i := 0 +for i < 5 { + fmt.Println(i) + i++ +} + +// Infinite loop +for { + // Loop forever + break // Use break to exit +} + +// Range loop +numbers := []int{1, 2, 3, 4, 5} +for index, value := range numbers { + fmt.Printf("Index: %d, Value: %d\n", index, value) +} + +// Range with only value +for _, value := range numbers { + fmt.Println(value) +} +``` +## Functions + +### Basic Function + +```go +func greet(name string) { + fmt.Printf("Hello, %s!\n", name) +} + +func main() { + greet("Alice") +} +``` + +### Function with Return Value +```go +func add(a, b int) int { + return a + b +} + +func main() { + result := add(5, 3) + fmt.Println(result) // 8 +} +``` + +### Multiple Return Values +```go +func divide(a, b float64) (float64, error) { + if b == 0 { + return 0, fmt.Errorf("division by zero") + } + return a / b, nil +} + +func main() { + result, err := divide(10, 2) + if err != nil { + fmt.Println("Error:", err) + } else { + fmt.Println("Result:", result) + } +} +``` + +### Named Return Values +```go +func rectangle(length, width float64) (area, perimeter float64) { + area = length * width + perimeter = 2 * (length + width) + return // naked return +} +``` + +### Variadic Functions +```go +func sum(numbers ...int) int { + total := 0 + for _, num := range numbers { + total += num + } + return total +} + +func main() { + fmt.Println(sum(1, 2, 3, 4, 5)) // 15 +} +``` + +### Anonymous Functions and Closures +```go +func main() { + // Anonymous function + func() { + fmt.Println("Anonymous function") + }() + + // Function assigned to variable + square := func(x int) int { + return x * x + } + fmt.Println(square(5)) // 25 + + // Closure + multiplier := func(factor int) func(int) int { + return func(x int) int { + return x * factor + } + } + + double := multiplier(2) + fmt.Println(double(5)) // 10 +} +``` +## Arrays and Slices + +| Feature | Array | Slice | +| -------------------- | ------------------------------------- | --------------------------------------- | +| Size | Fixed at declaration | Dynamic; can grow or shrink | +| Type | Size is part of type | Size **not** part of type | +| Memory Behavior | Value typeโ€”copy on assignment/passing | Reference typeโ€”sharing underlying data | +| Resizing | Not possible | `append()` can increase length/capacity | +| Underlying Mechanism | Direct contiguous data | Points to an underlying array | +| Use Case | When count is known and constant | For flexible, dynamic collections | +| Performance | Slightly faster, no indirection | Slight overhead, but more flexible | + + +### Arrays +```go +// Array declaration +var numbers [5]int +numbers[0] = 1 +numbers[1] = 2 + +// Array literal +fruits := [3]string{"apple", "banana", "orange"} + +// Let compiler count elements +colors := [...]string{"red", "green", "blue"} + +fmt.Println(len(fruits)) // 3 +``` + +### Slices +```go +// Slice declaration +var numbers []int + +// Slice literal +fruits := []string{"apple", "banana", "orange"} + +// Make slice with length and capacity +scores := make([]int, 5, 10) // length 5, capacity 10 + +// Append to slice +fruits = append(fruits, "grape") + +// Slice operations +numbers := []int{1, 2, 3, 4, 5} +subset := numbers[1:4] // [2, 3, 4] +first3 := numbers[:3] // [1, 2, 3] +last2 := numbers[3:] // [4, 5] + +fmt.Printf("Length: %d, Capacity: %d\n", len(fruits), cap(fruits)) +``` + +## Maps + +### Map Declaration and Usage +```go +// Map declaration +var ages map[string]int +ages = make(map[string]int) + +// Map literal +ages := map[string]int{ + "Alice": 30, + "Bob": 25, + "Carol": 35, +} + +// Adding/updating values +ages["David"] = 28 + +// Checking if key exists +age, exists := ages["Alice"] +if exists { + fmt.Printf("Alice is %d years old\n", age) +} + +// Deleting a key +delete(ages, "Bob") + +// Iterating over map +for name, age := range ages { + fmt.Printf("%s: %d\n", name, age) +} +``` +## Structs + +### Struct Definition and Usage +```go +// Define a struct +type Person struct { + Name string + Age int + City string +} + +func main() { + // Create struct instances + person1 := Person{ + Name: "Alice", + Age: 30, + City: "New York", + } + + person2 := Person{"Bob", 25, "London"} + + var person3 Person + person3.Name = "Carol" + person3.Age = 35 + + fmt.Printf("%+v\n", person1) +} +``` + +### Struct Methods +```go +type Rectangle struct { + Width float64 + Height float64 +} + +// Method with receiver +func (r Rectangle) Area() float64 { + return r.Width * r.Height +} + +// Method with pointer receiver (can modify struct) +func (r *Rectangle) Scale(factor float64) { + r.Width *= factor + r.Height *= factor +} + +func main() { + rect := Rectangle{Width: 10, Height: 5} + fmt.Println("Area:", rect.Area()) + + rect.Scale(2) + fmt.Printf("Scaled rectangle: %+v\n", rect) +} +``` + +### Embedded Structs +```go +type Address struct { + Street string + City string +} + +type Person struct { + Name string + Age int + Address // Embedded struct +} + +func main() { + person := Person{ + Name: "Alice", + Age: 30, + Address: Address{ + Street: "123 Main St", + City: "New York", + }, + } + + fmt.Println(person.Street) // Accessing embedded field directly +} +``` +## Interfaces + +### Interface Definition +```go +type Shape interface { + Area() float64 + Perimeter() float64 +} + +type Rectangle struct { + Width, Height float64 +} + +type Circle struct { + Radius float64 +} + +// Rectangle implements Shape interface +func (r Rectangle) Area() float64 { + return r.Width * r.Height +} + +func (r Rectangle) Perimeter() float64 { + return 2 * (r.Width + r.Height) +} + +// Circle implements Shape interface +func (c Circle) Area() float64 { + return 3.14159 * c.Radius * c.Radius +} + +func (c Circle) Perimeter() float64 { + return 2 * 3.14159 * c.Radius +} + +func printShapeInfo(s Shape) { + fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter()) +} + +func main() { + rect := Rectangle{Width: 10, Height: 5} + circle := Circle{Radius: 3} + + printShapeInfo(rect) + printShapeInfo(circle) +} +``` + +### Empty Interface +```go +func printAnything(v interface{}) { + fmt.Printf("Value: %v, Type: %T\n", v, v) +} + +func main() { + printAnything(42) + printAnything("hello") + printAnything([]int{1, 2, 3}) +} +``` + +### Type Assertions +```go +func checkType(v interface{}) { + switch v := v.(type) { + case int: + fmt.Printf("Integer: %d\n", v) + case string: + fmt.Printf("String: %s\n", v) + case bool: + fmt.Printf("Boolean: %t\n", v) + default: + fmt.Printf("Unknown type: %T\n", v) + } +} +``` +## Pointers + +### Basic Pointers +```go +func main() { + x := 42 + p := &x // p is a pointer to x + + fmt.Println("Value of x:", x) // 42 + fmt.Println("Address of x:", p) // memory address + fmt.Println("Value at p:", *p) // 42 (dereferencing) + + *p = 100 // Change value through pointer + fmt.Println("New value of x:", x) // 100 +} +``` + +### Pointers with Functions +```go +func increment(x *int) { + *x++ +} + +func main() { + num := 5 + increment(&num) + fmt.Println(num) // 6 +} +``` + +### Pointers with Structs +```go +type Person struct { + Name string + Age int +} + +func updateAge(p *Person, newAge int) { + p.Age = newAge // Go automatically dereferences +} + +func main() { + person := Person{Name: "Alice", Age: 30} + updateAge(&person, 31) + fmt.Printf("%+v\n", person) // {Name:Alice Age:31} +} +``` + +## Error Handling + +### Basic Error Handling +```go +import ( + "errors" + "fmt" +) + +func divide(a, b float64) (float64, error) { + if b == 0 { + return 0, errors.New("division by zero") + } + return a / b, nil +} + +func main() { + result, err := divide(10, 0) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Result:", result) +} +``` + +### Custom Error Types +```go +type ValidationError struct { + Field string + Message string +} + +func (e ValidationError) Error() string { + return fmt.Sprintf("validation error in field '%s': %s", e.Field, e.Message) +} + +func validateAge(age int) error { + if age < 0 { + return ValidationError{ + Field: "age", + Message: "must be non-negative", + } + } + if age > 150 { + return ValidationError{ + Field: "age", + Message: "must be realistic", + } + } + return nil +} +``` +## Goroutines and Channels + +### Goroutines +```go +import ( + "fmt" + "time" +) + +func sayHello(name string) { + for i := 0; i < 3; i++ { + fmt.Printf("Hello, %s! (%d)\n", name, i) + time.Sleep(100 * time.Millisecond) + } +} + +func main() { + go sayHello("Alice") // Run in goroutine + go sayHello("Bob") // Run in goroutine + sayHello("Charlie") // Run in main goroutine + + time.Sleep(1 * time.Second) // Wait for goroutines to finish +} +``` + +### Channels +```go +func main() { + // Create a channel + ch := make(chan string) + + // Send data to channel in goroutine + go func() { + ch <- "Hello from goroutine!" + }() + + // Receive data from channel + message := <-ch + fmt.Println(message) +} +``` + +### Buffered Channels +```go +func main() { + ch := make(chan int, 3) // Buffered channel with capacity 3 + + ch <- 1 + ch <- 2 + ch <- 3 + + fmt.Println(<-ch) // 1 + fmt.Println(<-ch) // 2 + fmt.Println(<-ch) // 3 +} +``` + +### Select Statement +```go +func main() { + ch1 := make(chan string) + ch2 := make(chan string) + + go func() { + time.Sleep(1 * time.Second) + ch1 <- "Channel 1" + }() + + go func() { + time.Sleep(2 * time.Second) + ch2 <- "Channel 2" + }() + + for i := 0; i < 2; i++ { + select { + case msg1 := <-ch1: + fmt.Println("Received:", msg1) + case msg2 := <-ch2: + fmt.Println("Received:", msg2) + case <-time.After(3 * time.Second): + fmt.Println("Timeout") + } + } +} +``` +## Packages and Modules +Package is initialized using - +```bash +go mod init github.com/sample/package_name +``` +>It is not necessary to in github url, but it is generally included since that's how go download it's external package + +### Creating a Package + +Create a file `math/calculator.go`: +```go +package math + +// Exported function (starts with capital letter) +func Add(a, b int) int { + return a + b +} + +// Unexported function (starts with lowercase letter) +func subtract(a, b int) int { + return a - b +} +``` + +### Using the Package +```go +package main + +import ( + "fmt" + "./math" // Local package +) + +func main() { + result := math.Add(5, 3) + fmt.Println(result) // 8 +} +``` + +### Go Modules + +Add dependencies: +```bash +go get github.com/gorilla/mux +``` + +Example `go.mod` file: +``` +module myproject + +go 1.19 + +require github.com/gorilla/mux v1.8.0 +``` + +## Testing + +### Basic Test +Create `calculator_test.go`: +```go +package main + +import "testing" + +func TestAdd(t *testing.T) { + result := Add(2, 3) + expected := 5 + + if result != expected { + t.Errorf("Add(2, 3) = %d; expected %d", result, expected) + } +} +``` + +### Table-Driven Tests +```go +func TestAddTable(t *testing.T) { + tests := []struct { + a, b int + expected int + }{ + {2, 3, 5}, + {-1, 1, 0}, + {0, 0, 0}, + {10, -5, 5}, + } + + for _, test := range tests { + result := Add(test.a, test.b) + if result != test.expected { + t.Errorf("Add(%d, %d) = %d; expected %d", + test.a, test.b, result, test.expected) + } + } +} +``` + +Run tests: +```bash +go test # Run tests +go test -v # Verbose output +go test -bench=. # Run benchmarks +go test -cover # Show coverage +``` + +# Intermediate Go Language Tutorial + +## Enums with iota + +Go doesn't have built-in enums, but you can create enum-like behavior using constants and `iota`: + +```go +type Status int + +const ( + StatusPending Status = iota // 0 + StatusRunning // 1 + StatusComplete // 2 + StatusFailed // 3 +) + +func (s Status) String() string { + switch s { + case StatusPending: + return "Pending" + case StatusRunning: + return "Running" + case StatusComplete: + return "Complete" + case StatusFailed: + return "Failed" + default: + return "Unknown" + } +} + +func main() { + status := StatusRunning + fmt.Println(status) // Running + fmt.Println(int(status)) // 1 +} +``` + +### Advanced iota Usage +```go +type FilePermission int + +const ( + Read FilePermission = 1 << iota // 1 (binary: 001) + Write // 2 (binary: 010) + Execute // 4 (binary: 100) +) + +func main() { + permission := Read | Write // Combine permissions + fmt.Printf("Permission: %b\n", permission) // 11 (binary) + + if permission&Read != 0 { + fmt.Println("Has read permission") + } +} +``` + +## HTTP Server and Client (net/http) + +### Basic HTTP Server +```go +package main + +import ( + "fmt" + "log" + "net/http" +) + +func homeHandler(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") +} + +func aboutHandler(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "About us page") +} + +func main() { + http.HandleFunc("/", homeHandler) + http.HandleFunc("/about", aboutHandler) + + fmt.Println("Server starting on :8080") + log.Fatal(http.ListenAndServe(":8080", nil)) +} +``` + +### HTTP Server with Mux Router +```go +package main + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "strconv" +) + +type User struct { + ID int `json:"id"` + Name string `json:"name"` + Email string `json:"email"` +} + +var users = []User{ + {1, "Alice", "alice@example.com"}, + {2, "Bob", "bob@example.com"}, +} + +func getUsersHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(users) +} + +func getUserHandler(w http.ResponseWriter, r *http.Request) { + idStr := r.URL.Path[len("/users/"):] + id, err := strconv.Atoi(idStr) + if err != nil { + http.Error(w, "Invalid user ID", http.StatusBadRequest) + return + } + + for _, user := range users { + if user.ID == id { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(user) + return + } + } + + http.Error(w, "User not found", http.StatusNotFound) +} + +func main() { + http.HandleFunc("/users", getUsersHandler) + http.HandleFunc("/users/", getUserHandler) + + fmt.Println("Server starting on :8080") + log.Fatal(http.ListenAndServe(":8080", nil)) +} +``` + +### HTTP Client +```go +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" +) + +type Post struct { + UserID int `json:"userId"` + ID int `json:"id"` + Title string `json:"title"` + Body string `json:"body"` +} + +func main() { + // GET request + resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1") + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Printf("Error reading body: %v\n", err) + return + } + + var post Post + json.Unmarshal(body, &post) + fmt.Printf("Post: %+v\n", post) + + // POST request + newPost := Post{ + UserID: 1, + Title: "My New Post", + Body: "This is the body of my new post", + } + + jsonData, _ := json.Marshal(newPost) + resp, err = http.Post( + "https://jsonplaceholder.typicode.com/posts", + "application/json", + bytes.NewBuffer(jsonData), + ) + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + defer resp.Body.Close() + + fmt.Printf("Status: %s\n", resp.Status) +} +``` + +## JSON Parsing and Marshaling + +### Basic JSON Operations +```go +package main + +import ( + "encoding/json" + "fmt" +) + +type Person struct { + Name string `json:"name"` + Age int `json:"age"` + Email string `json:"email,omitempty"` + Private string `json:"-"` // This field won't be marshaled +} + +func main() { + // Marshal (Go struct to JSON) + person := Person{ + Name: "Alice", + Age: 30, + Email: "alice@example.com", + Private: "secret", + } + + jsonData, err := json.Marshal(person) + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + + fmt.Printf("JSON: %s\n", jsonData) + + // Unmarshal (JSON to Go struct) + jsonStr := `{"name":"Bob","age":25}` + var newPerson Person + + err = json.Unmarshal([]byte(jsonStr), &newPerson) + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + + fmt.Printf("Person: %+v\n", newPerson) +} +``` + +### Working with Dynamic JSON +```go +package main + +import ( + "encoding/json" + "fmt" +) + +func main() { + // Parse unknown JSON structure + jsonStr := `{ + "name": "Alice", + "age": 30, + "hobbies": ["reading", "swimming"], + "address": { + "street": "123 Main St", + "city": "New York" + } + }` + + var data map[string]interface{} + json.Unmarshal([]byte(jsonStr), &data) + + fmt.Printf("Name: %s\n", data["name"]) + fmt.Printf("Age: %.0f\n", data["age"]) + + // Access nested data + address := data["address"].(map[string]interface{}) + fmt.Printf("City: %s\n", address["city"]) + + // Access array + hobbies := data["hobbies"].([]interface{}) + for i, hobby := range hobbies { + fmt.Printf("Hobby %d: %s\n", i+1, hobby) + } +} +``` + +## Embed Module (Go 1.16+) + +The `embed` package allows you to embed files directly into your Go binary: + +### Embedding Files +```go +package main + +import ( + _ "embed" + "fmt" +) + +//go:embed version.txt +var version string + +//go:embed config.json +var configData []byte + +func main() { + fmt.Printf("Version: %s\n", version) + fmt.Printf("Config size: %d bytes\n", len(configData)) +} +``` + +### Embedding Multiple Files +```go +package main + +import ( + "embed" + "fmt" + "io/fs" +) + +//go:embed static/* +var staticFiles embed.FS + +//go:embed templates/*.html +var templates embed.FS + +func main() { + // Read a specific file + data, err := staticFiles.ReadFile("static/style.css") + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + fmt.Printf("CSS size: %d bytes\n", len(data)) + + // List all embedded files + fs.WalkDir(templates, ".", func(path string, d fs.DirEntry, err error) error { + if !d.IsDir() { + fmt.Printf("Template: %s\n", path) + } + return nil + }) +} +``` + +### Embedding with HTTP Server +```go +package main + +import ( + "embed" + "fmt" + "net/http" +) + +//go:embed static/* +var staticFiles embed.FS + +func main() { + // Serve embedded static files + http.Handle("/static/", http.FileServer(http.FS(staticFiles))) + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello! Static files are served from /static/") + }) + + fmt.Println("Server starting on :8080") + http.ListenAndServe(":8080", nil) +} +``` + +## Context Package + +The `context` package is essential for managing request lifecycles, timeouts, and cancellation: + +```go +package main + +import ( + "context" + "fmt" + "net/http" + "time" +) + +func longRunningTask(ctx context.Context) error { + select { + case <-time.After(5 * time.Second): + fmt.Println("Task completed") + return nil + case <-ctx.Done(): + fmt.Println("Task cancelled:", ctx.Err()) + return ctx.Err() + } +} + +func handlerWithTimeout(w http.ResponseWriter, r *http.Request) { + // Create context with timeout + ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second) + defer cancel() + + err := longRunningTask(ctx) + if err != nil { + http.Error(w, "Request timeout", http.StatusRequestTimeout) + return + } + + fmt.Fprintf(w, "Task completed successfully") +} + +func main() { + http.HandleFunc("/task", handlerWithTimeout) + fmt.Println("Server starting on :8080") + http.ListenAndServe(":8080", nil) +} +``` + +## Working with Databases + +### Using database/sql with SQLite +```go +package main + +import ( + "database/sql" + "fmt" + "log" + + _ "github.com/mattn/go-sqlite3" +) + +type User struct { + ID int + Name string + Email string +} + +func main() { + db, err := sql.Open("sqlite3", "./users.db") + if err != nil { + log.Fatal(err) + } + defer db.Close() + + // Create table + createTable := ` + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL + );` + + _, err = db.Exec(createTable) + if err != nil { + log.Fatal(err) + } + + // Insert user + insertUser := `INSERT INTO users (name, email) VALUES (?, ?)` + result, err := db.Exec(insertUser, "Alice", "alice@example.com") + if err != nil { + log.Fatal(err) + } + + id, _ := result.LastInsertId() + fmt.Printf("Inserted user with ID: %d\n", id) + + // Query users + rows, err := db.Query("SELECT id, name, email FROM users") + if err != nil { + log.Fatal(err) + } + defer rows.Close() + + for rows.Next() { + var user User + err := rows.Scan(&user.ID, &user.Name, &user.Email) + if err != nil { + log.Fatal(err) + } + fmt.Printf("User: %+v\n", user) + } +} +``` + +## File Operations and I/O + +### Reading and Writing Files +```go +package main + +import ( + "bufio" + "fmt" + "io" + "os" +) + +func main() { + // Write to file + file, err := os.Create("example.txt") + if err != nil { + fmt.Printf("Error creating file: %v\n", err) + return + } + defer file.Close() + + writer := bufio.NewWriter(file) + writer.WriteString("Hello, World!\n") + writer.WriteString("This is a test file.\n") + writer.Flush() + + // Read entire file + content, err := os.ReadFile("example.txt") + if err != nil { + fmt.Printf("Error reading file: %v\n", err) + return + } + fmt.Printf("File content:\n%s", content) + + // Read file line by line + file, err = os.Open("example.txt") + if err != nil { + fmt.Printf("Error opening file: %v\n", err) + return + } + defer file.Close() + + scanner := bufio.NewScanner(file) + lineNum := 1 + for scanner.Scan() { + fmt.Printf("Line %d: %s\n", lineNum, scanner.Text()) + lineNum++ + } +} +``` + +## Regular Expressions + +```go +package main + +import ( + "fmt" + "regexp" +) + +func main() { + // Compile regex pattern + emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`) + + emails := []string{ + "user@example.com", + "invalid-email", + "test.email+tag@domain.co.uk", + } + + for _, email := range emails { + if emailRegex.MatchString(email) { + fmt.Printf("%s is valid\n", email) + } else { + fmt.Printf("%s is invalid\n", email) + } + } + + // Find and replace + text := "The quick brown fox jumps over the lazy dog" + wordRegex := regexp.MustCompile(`\b\w{4}\b`) // Find 4-letter words + + matches := wordRegex.FindAllString(text, -1) + fmt.Printf("4-letter words: %v\n", matches) + + // Replace matches + result := wordRegex.ReplaceAllString(text, "****") + fmt.Printf("Replaced: %s\n", result) +} +``` + +## Working with Time + +```go +package main + +import ( + "fmt" + "time" +) + +func main() { + now := time.Now() + fmt.Printf("Current time: %s\n", now.Format("2006-01-02 15:04:05")) + + // Parse time from string + timeStr := "2023-12-25 10:30:00" + parsedTime, err := time.Parse("2006-01-02 15:04:05", timeStr) + if err != nil { + fmt.Printf("Error parsing time: %v\n", err) + return + } + + // Time calculations + duration := now.Sub(parsedTime) + fmt.Printf("Duration since Christmas: %s\n", duration) + + // Add time + futureTime := now.Add(24 * time.Hour) + fmt.Printf("Tomorrow: %s\n", futureTime.Format("2006-01-02")) + + // Timer and Ticker + timer := time.NewTimer(2 * time.Second) + go func() { + <-timer.C + fmt.Println("Timer expired!") + }() + + ticker := time.NewTicker(1 * time.Second) + go func() { + for t := range ticker.C { + fmt.Printf("Tick at %s\n", t.Format("15:04:05")) + } + }() + + time.Sleep(5 * time.Second) + ticker.Stop() +} +``` +## Tutorials + +### Official Documentation +- [Go Documentation](https://golang.org/doc/) - Official Go documentation and tutorials +- [Go Tour](https://tour.golang.org/) - Interactive introduction to Go +- [Effective Go](https://golang.org/doc/effective_go.html) - Tips for writing clear, idiomatic Go code + +### Video Tutorials +- [Go in 100 seconds](https://youtu.be/446E-r0rXHI?si=vD0E4tR2smNWmTAg) +- [Go Programming Tutorial](https://youtu.be/un6ZyFkqFKo?si=FNSF0033XDq_mke1) - Complete beginner tutorial +- [Go Crash Course](https://www.youtube.com/watch?v=SqrbIlUwR0U) - Quick introduction to Go +- [Advanced Go Patterns](https://www.youtube.com/watch?v=rFejpH_tAHM) - Advanced Go programming techniques + +### Books and Resources +- [The Go Programming Language](http://www.gopl.io/) - Comprehensive book by Alan Donovan and Brian Kernighan +- [Go by Example](https://gobyexample.com/) - Hands-on introduction using annotated example programs +- [Go Web Examples](https://gowebexamples.com/) - Learn web development with Go + +### Practice Platforms +- [Boot.dev](https://www.boot.dev/courses/learn-golang) - One of the best platform to learn Go. +- [Go Playground](https://play.golang.org/) - Online Go compiler and sharing tool +- [Exercism Go Track](https://exercism.io/tracks/go) - Practice exercises with mentoring + +This tutorial covers the essential concepts of Go programming. Go's simplicity, performance, and excellent concurrency support make it an excellent choice for modern software development, especially for backend services, cloud applications, and system tools. \ No newline at end of file diff --git a/README.md b/README.md index 044a9cc..a1ba013 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Weโ€™ve compiled cheat sheets on the top 9 tech stacks used in the C4GT Communit - ๐Ÿ“„ [Typescript](./Languages/Typescript.md) - ๐Ÿ“„ [Markdown](./Languages/markdown.md) - ๐Ÿ“„ [Python](./Languages/python.md) + - ๐Ÿ“„ [Golang](./Languages/golang.md) diff --git a/resources.html b/resources.html index cc7ce32..3daf83e 100644 --- a/resources.html +++ b/resources.html @@ -113,6 +113,7 @@

๐Ÿ“‚ Languages

  • ๐Ÿ“„ TypeScript
  • ๐Ÿ“„ Markdown
  • ๐Ÿ“„ Python
  • +
  • ๐Ÿ“„ Golang