├── basic_file ├── hello ├── src ├── car-rental-system │ ├── go.mod │ ├── rental_system_models │ │ └── models.go │ ├── main.go │ └── handlers │ │ └── rental_system_handler.go ├── hello.go ├── etl_strings.go ├── grpc_exercise │ ├── proto │ │ ├── greeter.proto │ │ ├── greeter_grpc.pb.go │ │ └── greeter.pb.go │ ├── go.mod │ ├── client │ │ └── main.go │ ├── server │ │ └── main.go │ └── go.sum ├── word_count.go ├── basic_file_reader.go ├── sublist.go ├── api_exercise │ ├── go.mod │ ├── main.go │ └── go.sum ├── command_line_app.go ├── type_agnostic_queue.go ├── grade-school.go ├── json_processor.go ├── context_aware_http_server.go ├── concurrency.go ├── car_rental_system_refactored.go ├── mini_blog.go └── car_rental_system.go ├── go.mod ├── go.sum ├── README.md └── user_data └── users.json /basic_file: -------------------------------------------------------------------------------- 1 | This is data inside the file. 2 | This will open in terminal. -------------------------------------------------------------------------------- /hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethdomperin2018/go_forum/HEAD/hello -------------------------------------------------------------------------------- /src/car-rental-system/go.mod: -------------------------------------------------------------------------------- 1 | module car-rental-system 2 | 3 | go 1.23.7 4 | -------------------------------------------------------------------------------- /src/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | name := "Alice" 7 | age := 30 8 | fmt.Printf("Name: %s, Age: %d\n", name, age) 9 | fmt.Println("Hello, World!") 10 | i := 37 11 | fmt.Println(i) 12 | } 13 | -------------------------------------------------------------------------------- /src/etl_strings.go: -------------------------------------------------------------------------------- 1 | package etl 2 | 3 | import "strings" 4 | 5 | func Transform(in map[int][]string) map[string]int { 6 | out := make(map[string]int) 7 | for score, letters := range in { 8 | for _, letter := range letters { 9 | out[strings.ToLower(letter)] = score 10 | } 11 | } 12 | return out 13 | } 14 | -------------------------------------------------------------------------------- /src/grpc_exercise/proto/greeter.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = ".;greeter"; 4 | 5 | service Greeter { 6 | rpc SayHello (HelloRequest) returns (HelloReply) {} 7 | } 8 | 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | 13 | message HelloReply { 14 | string message = 1; 15 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module example/hello 2 | 3 | go 1.23.7 4 | 5 | require ( 6 | filippo.io/edwards25519 v1.1.0 // indirect 7 | github.com/go-sql-driver/mysql v1.9.2 // indirect 8 | github.com/jinzhu/inflection v1.0.0 // indirect 9 | github.com/jinzhu/now v1.1.5 // indirect 10 | golang.org/x/text v0.24.0 // indirect 11 | gorm.io/driver/mysql v1.5.7 // indirect 12 | gorm.io/gorm v1.25.12 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /src/grpc_exercise/go.mod: -------------------------------------------------------------------------------- 1 | module grpc_exercise 2 | 3 | go 1.23.7 4 | 5 | require google.golang.org/grpc v1.71.1 6 | 7 | require ( 8 | golang.org/x/net v0.34.0 // indirect 9 | golang.org/x/sys v0.29.0 // indirect 10 | golang.org/x/text v0.21.0 // indirect 11 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect 12 | google.golang.org/protobuf v1.36.4 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /src/word_count.go: -------------------------------------------------------------------------------- 1 | package wordcount 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | ) 7 | 8 | type Frequency map[string]int 9 | 10 | func WordCount(input string) Frequency { 11 | counts := make(Frequency) 12 | wordPattern := regexp.MustCompile(`\b[\w']+\b`) 13 | words := wordPattern.FindAllString(input, -1) 14 | 15 | for _, word := range words { 16 | lowerWord := strings.ToLower(word) 17 | counts[lowerWord]++ 18 | } 19 | 20 | return counts 21 | } 22 | -------------------------------------------------------------------------------- /src/car-rental-system/rental_system_models/models.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Car struct { 4 | ID int 5 | Make string 6 | Model string 7 | Year int 8 | LicensePlate string 9 | RentalPricePerDay float64 10 | IsAvailable bool 11 | } 12 | 13 | type Customer struct { 14 | Name string 15 | ContactDetails string 16 | DriversLicense string 17 | } 18 | 19 | type Reservation struct { 20 | ID int 21 | Customer Customer 22 | CarID int 23 | StartDate string 24 | EndDate string 25 | TotalPrice float64 26 | Paid bool 27 | } -------------------------------------------------------------------------------- /src/grpc_exercise/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "os" 7 | "time" 8 | 9 | "google.golang.org/grpc" 10 | pb "grpc_exercise/proto" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 15 | if err != nil { 16 | log.Fatalf("did not connect: %v", err) 17 | } 18 | defer conn.Close() 19 | c := pb.NewGreeterClient(conn) 20 | 21 | name := "World" 22 | if len(os.Args) > 1 { 23 | name = os.Args[1] 24 | } 25 | 26 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 27 | defer cancel() 28 | r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name}) 29 | if err != nil { 30 | log.Fatalf("could not greet: %v", err) 31 | } 32 | log.Printf("Greeting: %s", r.Message) 33 | } -------------------------------------------------------------------------------- /src/grpc_exercise/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net" 7 | 8 | "google.golang.org/grpc" 9 | pb "grpc_exercise/proto" 10 | ) 11 | 12 | type server struct { 13 | pb.UnimplementedGreeterServer 14 | } 15 | 16 | func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { 17 | return &pb.HelloReply{Message: "Hello " + req.Name}, nil 18 | } 19 | 20 | func main() { 21 | lis, err := net.Listen("tcp", ":50051") 22 | if err != nil { 23 | log.Fatalf("failed to listen: %v", err) 24 | } 25 | s := grpc.NewServer() 26 | pb.RegisterGreeterServer(s, &server{}) 27 | log.Printf("server listening at %v", lis.Addr()) 28 | if err := s.Serve(lis); err != nil { 29 | log.Fatalf("failed to serve: %v", err) 30 | } 31 | } -------------------------------------------------------------------------------- /src/basic_file_reader.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | // Prompt the user to enter the file path 11 | fmt.Print("Enter the file path: ") 12 | var filePath string 13 | fmt.Scanln(&filePath) 14 | 15 | // Try to open the file 16 | file, err := os.Open(filePath) 17 | if err != nil { 18 | fmt.Println("Error opening file:", err) 19 | return 20 | } 21 | defer file.Close() // Ensure the file is closed when the function ends 22 | 23 | // Read and print the contents of the file 24 | fmt.Println("File contents:") 25 | scanner := bufio.NewScanner(file) 26 | for scanner.Scan() { 27 | fmt.Println(scanner.Text()) 28 | } 29 | 30 | // Check for any errors encountered during reading 31 | if err := scanner.Err(); err != nil { 32 | fmt.Println("Error reading file:", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/sublist.go: -------------------------------------------------------------------------------- 1 | package sublist 2 | 3 | // isSublist checks if list a is contained within list b 4 | func isSublist(a, b []int) bool { 5 | if len(a) == 0 { 6 | return true 7 | } 8 | if len(a) > len(b) { 9 | return false 10 | } 11 | 12 | for i := 0; i <= len(b)-len(a); i++ { 13 | match := true 14 | for j := 0; j < len(a); j++ { 15 | if a[j] != b[i+j] { 16 | match = false 17 | break 18 | } 19 | } 20 | if match { 21 | return true 22 | } 23 | } 24 | return false 25 | } 26 | 27 | // Sublist determines the relationship between two lists 28 | func Sublist(l1, l2 []int) Relation { 29 | switch { 30 | case len(l1) == len(l2) && isSublist(l1, l2): 31 | return RelationEqual 32 | case len(l1) < len(l2) && isSublist(l1, l2): 33 | return RelationSublist 34 | case len(l1) > len(l2) && isSublist(l2, l1): 35 | return RelationSuperlist 36 | default: 37 | return RelationUnequal 38 | } 39 | } -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= 2 | filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= 3 | github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= 4 | github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU= 5 | github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= 6 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 7 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 8 | github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 9 | github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 10 | golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= 11 | golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= 12 | gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= 13 | gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= 14 | gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= 15 | gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= 16 | gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golang Projects Repository 2 | 3 | Welcome to my **Golang Projects** repository! This repo is a collection of my learning journey and implementations, showcasing concepts ranging from the basics of Go to building advanced applications like APIs, mini blogs, and a fully designed car rental system. 4 | 5 | --- 6 | 7 | ## 🔍 What's Inside? 8 | 9 | ### 1. **Golang Basics** 10 | - Covers foundational concepts such as variables, control structures, concurrency, and more. 11 | - Beginner-friendly code examples and implementations. 12 | 13 | ### 2. **API Development** 14 | - RESTful APIs built using: 15 | - Standard Go libraries. 16 | - Frameworks like **Gin** for rapid development. 17 | - Includes JWT authentication and CRUD operations. 18 | - Examples include: 19 | - A **Book Management System**. 20 | 21 | ### 3. **Mini Blog** 22 | - A lightweight blogging platform with: 23 | - Post creation, retrieval, and management. 24 | 25 | ### 4. **Car Rental System** 26 | - A comprehensive project demonstrating: 27 | - Structured database schema with auto-migration using GORM. 28 | - Advanced features like transaction handling. 29 | 30 | --- 31 | 32 | ## 🛠️ Technologies Used 33 | - **Golang**: The backbone of all implementations. 34 | - **Gin Framework**: For faster API development. 35 | - **GORM**: For ORM and database operations. 36 | - **JWT**: For secure authentication. 37 | -------------------------------------------------------------------------------- /src/api_exercise/go.mod: -------------------------------------------------------------------------------- 1 | module api_exercise 2 | 3 | go 1.23.7 4 | 5 | require ( 6 | github.com/bytedance/sonic v1.13.2 // indirect 7 | github.com/bytedance/sonic/loader v0.2.4 // indirect 8 | github.com/cloudwego/base64x v0.1.5 // indirect 9 | github.com/cloudwego/iasm v0.2.0 // indirect 10 | github.com/gabriel-vasile/mimetype v1.4.8 // indirect 11 | github.com/gin-contrib/sse v1.1.0 // indirect 12 | github.com/gin-gonic/gin v1.10.0 // indirect 13 | github.com/go-playground/locales v0.14.1 // indirect 14 | github.com/go-playground/universal-translator v0.18.1 // indirect 15 | github.com/go-playground/validator/v10 v10.26.0 // indirect 16 | github.com/goccy/go-json v0.10.5 // indirect 17 | github.com/json-iterator/go v1.1.12 // indirect 18 | github.com/klauspost/cpuid/v2 v2.2.10 // indirect 19 | github.com/leodido/go-urn v1.4.0 // indirect 20 | github.com/mattn/go-isatty v0.0.20 // indirect 21 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 22 | github.com/modern-go/reflect2 v1.0.2 // indirect 23 | github.com/pelletier/go-toml/v2 v2.2.4 // indirect 24 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 25 | github.com/ugorji/go/codec v1.2.12 // indirect 26 | golang.org/x/arch v0.16.0 // indirect 27 | golang.org/x/crypto v0.37.0 // indirect 28 | golang.org/x/net v0.39.0 // indirect 29 | golang.org/x/sys v0.32.0 // indirect 30 | golang.org/x/text v0.24.0 // indirect 31 | google.golang.org/protobuf v1.36.6 // indirect 32 | gopkg.in/yaml.v3 v3.0.1 // indirect 33 | ) 34 | -------------------------------------------------------------------------------- /src/car-rental-system/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "car-rental-system/models" 5 | "car-rental-system/services" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | // Initialize Rental System 11 | rentalSystem := services.NewRentalSystem() 12 | 13 | // Adding cars 14 | rentalSystem.AddCar(models.Car{ID: 1, Make: "Toyota", Model: "Corolla", Year: 2020, LicensePlate: "ABC123", RentalPricePerDay: 50, IsAvailable: true}) 15 | rentalSystem.AddCar(models.Car{ID: 2, Make: "Honda", Model: "Civic", Year: 2021, LicensePlate: "XYZ789", RentalPricePerDay: 60, IsAvailable: true}) 16 | 17 | // Searching cars 18 | fmt.Println("Available Cars:", rentalSystem.SearchCars("Toyota", 100)) 19 | 20 | // Creating reservation 21 | customer := models.Customer{Name: "John Doe", ContactDetails: "john.doe@example.com", DriversLicense: "D123456"} 22 | reservation, err := rentalSystem.CreateReservation(customer, 1, "2025-03-29", "2025-03-30") 23 | if err == nil { 24 | fmt.Println("Reservation created:", *reservation) 25 | } 26 | 27 | // Processing payment 28 | if err := rentalSystem.ProcessPayment(reservation.ID); err == nil { 29 | fmt.Println("Payment successful") 30 | } 31 | 32 | // Modifying reservation 33 | if err := rentalSystem.ModifyReservation(reservation.ID, "2025-04-01", "2025-04-02"); err == nil { 34 | fmt.Println("Reservation modified successfully") 35 | } 36 | 37 | // Canceling reservation 38 | if err := rentalSystem.CancelReservation(reservation.ID); err == nil { 39 | fmt.Println("Reservation canceled.") 40 | } 41 | } -------------------------------------------------------------------------------- /src/command_line_app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "strconv" 9 | ) 10 | 11 | // recoverFromPanic handles unexpected panics gracefully 12 | func recoverFromPanic() { 13 | if r := recover(); r != nil { 14 | fmt.Println("Recovered from panic:", r) 15 | } 16 | } 17 | 18 | func main() { 19 | defer recoverFromPanic() // Ensure recovery from unexpected errors 20 | 21 | // Define a flag that accepts a comma-separated list of numbers 22 | input := flag.String("numbers", "", "Comma-separated list of numbers") 23 | flag.Parse() 24 | 25 | if *input == "" { 26 | fmt.Println("Error: No numbers provided. Use -numbers flag.") 27 | os.Exit(1) 28 | } 29 | 30 | nums := parseNumbers(*input) 31 | sum := 0 32 | for _, num := range nums { 33 | sum += num 34 | } 35 | 36 | fmt.Println("Sum of valid numbers:", sum) 37 | } 38 | 39 | func parseNumbers(input string) []int { 40 | var numbers []int 41 | values := splitString(input) 42 | 43 | for _, val := range values { 44 | num, err := convertToInt(val) 45 | if err != nil { 46 | fmt.Printf("Skipping invalid input '%s': %v\n", val, err) 47 | continue 48 | } 49 | numbers = append(numbers, num) 50 | } 51 | return numbers 52 | } 53 | 54 | func splitString(input string) []string { 55 | return append([]string{input}, flag.Args()...) 56 | } 57 | 58 | func convertToInt(value string) (int, error) { 59 | num, err := strconv.Atoi(value) 60 | if err != nil { 61 | return 0, errors.New("not a valid integer") 62 | } 63 | return num, nil 64 | } 65 | -------------------------------------------------------------------------------- /src/type_agnostic_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Queue is a generic FIFO queue with only int and string as allowed types 6 | type AllowedTypes interface { 7 | int | string 8 | } 9 | type Queue[T AllowedTypes] struct { 10 | items []T 11 | } 12 | 13 | // Create new empty queue 14 | func NewQueue[T AllowedTypes]() *Queue[T] { 15 | return &Queue[T]{items: make([]T, 0)} 16 | } 17 | 18 | // Add item to end of queue 19 | func (q *Queue[T]) Enqueue(item T) { 20 | q.items = append(q.items, item) 21 | } 22 | 23 | // Remove and return first item 24 | func (q *Queue[T]) Dequeue() (T, bool) { 25 | if len(q.items) == 0 { 26 | var zero T 27 | return zero, false 28 | } 29 | item := q.items[0] 30 | q.items = q.items[1:] 31 | return item, true 32 | } 33 | 34 | // View first item without removing 35 | func (q *Queue[T]) Peek() (T, bool) { 36 | if len(q.items) == 0 { 37 | var zero T 38 | return zero, false 39 | } 40 | return q.items[0], true 41 | } 42 | 43 | func main() { 44 | // Create queue 45 | q := NewQueue[int]() 46 | 47 | // Enqueue some items 48 | q.Enqueue(2) 49 | q.Enqueue(3) 50 | q.Enqueue(6) 51 | 52 | // Peek at first item 53 | if first, ok := q.Peek(); ok { 54 | fmt.Println("Peek:", first) // "first" 55 | } 56 | 57 | // Process all items 58 | fmt.Println("Processing queue:") 59 | for { 60 | item, ok := q.Dequeue() 61 | if !ok { 62 | break 63 | } 64 | fmt.Println(item) 65 | } 66 | q.Enqueue(9) 67 | value, exists := q.Peek() 68 | fmt.Printf("Peek value: %d, Exists: %t\n", value, exists) 69 | if _, ok := q.Dequeue(); !ok { 70 | fmt.Println("Queue is empty") 71 | } 72 | } -------------------------------------------------------------------------------- /src/grade-school.go: -------------------------------------------------------------------------------- 1 | package school 2 | 3 | import ( 4 | "sort" 5 | ) 6 | 7 | // Grade represents a school grade with its students 8 | type Grade struct { 9 | Level int 10 | Students []string 11 | } 12 | 13 | // School represents the entire school roster 14 | type School struct { 15 | grades map[int]*Grade 16 | } 17 | 18 | // New creates a new School instance 19 | func New() *School { 20 | return &School{ 21 | grades: make(map[int]*Grade), 22 | } 23 | } 24 | 25 | // Add a student to a grade 26 | func (s *School) Add(student string, grade int) { 27 | if _, exists := s.grades[grade]; !exists { 28 | s.grades[grade] = &Grade{Level: grade} 29 | } 30 | 31 | for _, name := range s.grades[grade].Students { 32 | if name == student { 33 | return // Student already exists in this grade 34 | } 35 | } 36 | 37 | s.grades[grade].Students = append(s.grades[grade].Students, student) 38 | sort.Strings(s.grades[grade].Students) 39 | } 40 | 41 | // Grade returns students in a specific grade 42 | func (s *School) Grade(level int) []string { 43 | if grade, exists := s.grades[level]; exists { 44 | return grade.Students 45 | } 46 | return []string{} 47 | } 48 | 49 | // Enrollment returns all grades with their students, sorted 50 | func (s *School) Enrollment() []Grade { 51 | var result []Grade 52 | 53 | // Get all grade levels and sort them 54 | var levels []int 55 | for level := range s.grades { 56 | levels = append(levels, level) 57 | } 58 | sort.Ints(levels) 59 | 60 | // Build the result in order 61 | for _, level := range levels { 62 | result = append(result, *s.grades[level]) 63 | } 64 | 65 | return result 66 | } -------------------------------------------------------------------------------- /user_data/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Leanne Graham", 5 | "email": "Sincere@april.biz", 6 | "username": "Bret", 7 | "avatar": "" 8 | }, 9 | { 10 | "id": 2, 11 | "name": "Ervin Howell", 12 | "email": "Shanna@melissa.tv", 13 | "username": "Antonette", 14 | "avatar": "" 15 | }, 16 | { 17 | "id": 3, 18 | "name": "Clementine Bauch", 19 | "email": "Nathan@yesenia.net", 20 | "username": "Samantha", 21 | "avatar": "" 22 | }, 23 | { 24 | "id": 4, 25 | "name": "Patricia Lebsack", 26 | "email": "Julianne.OConner@kory.org", 27 | "username": "Karianne", 28 | "avatar": "" 29 | }, 30 | { 31 | "id": 5, 32 | "name": "Chelsey Dietrich", 33 | "email": "Lucio_Hettinger@annie.ca", 34 | "username": "Kamren", 35 | "avatar": "" 36 | }, 37 | { 38 | "id": 6, 39 | "name": "Mrs. Dennis Schulist", 40 | "email": "Karley_Dach@jasper.info", 41 | "username": "Leopoldo_Corkery", 42 | "avatar": "" 43 | }, 44 | { 45 | "id": 7, 46 | "name": "Kurtis Weissnat", 47 | "email": "Telly.Hoeger@billy.biz", 48 | "username": "Elwyn.Skiles", 49 | "avatar": "" 50 | }, 51 | { 52 | "id": 8, 53 | "name": "Nicholas Runolfsdottir V", 54 | "email": "Sherwood@rosamond.me", 55 | "username": "Maxime_Nienow", 56 | "avatar": "" 57 | }, 58 | { 59 | "id": 9, 60 | "name": "Glenna Reichert", 61 | "email": "Chaim_McDermott@dana.io", 62 | "username": "Delphine", 63 | "avatar": "" 64 | }, 65 | { 66 | "id": 10, 67 | "name": "Clementina DuBuque", 68 | "email": "Rey.Padberg@karina.biz", 69 | "username": "Moriah.Stanton", 70 | "avatar": "" 71 | } 72 | ] -------------------------------------------------------------------------------- /src/json_processor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | ) 10 | 11 | type User struct { 12 | ID int `json:"id"` 13 | Name string `json:"name"` 14 | Email string `json:"email"` 15 | Username string `json:"username"` 16 | Avatar string `json:"avatar"` // Using placeholder photo URL 17 | } 18 | 19 | func main() { 20 | resp, err := http.Get("https://jsonplaceholder.typicode.com/users") 21 | if err != nil { 22 | fmt.Println("Error fetching data:", err) 23 | return 24 | } 25 | defer resp.Body.Close() 26 | 27 | body, err := io.ReadAll(resp.Body) 28 | if err != nil { 29 | fmt.Println("Error reading response:", err) 30 | return 31 | } 32 | 33 | var users []User 34 | if err := json.Unmarshal(body, &users); err != nil { 35 | fmt.Println("Error unmarshaling JSON:", err) 36 | return 37 | } 38 | 39 | // Create output directory 40 | if err := os.Mkdir("user_data", 0755); err != nil && !os.IsExist(err) { 41 | fmt.Println("Error creating directory:", err) 42 | return 43 | } 44 | 45 | // Process first 10 users (instead of 100 as JSONPlaceholder only has 10 users) 46 | for i, user := range users { 47 | if i >= 10 { 48 | break 49 | } 50 | 51 | // Download avatar 52 | if err := downloadFile(user.Avatar, fmt.Sprintf("user_data/avatar_%d.jpg", user.ID)); err != nil { 53 | fmt.Printf("Error downloading avatar for user %d: %v\n", user.ID, err) 54 | continue 55 | } 56 | } 57 | 58 | // Save user data to JSON 59 | userJSON, err := json.MarshalIndent(users[:10], "", " ") 60 | if err != nil { 61 | fmt.Println("Error marshaling user data:", err) 62 | return 63 | } 64 | 65 | if err := os.WriteFile("user_data/users.json", userJSON, 0644); err != nil { 66 | fmt.Println("Error writing user data file:", err) 67 | return 68 | } 69 | 70 | fmt.Println("Successfully processed users. Data saved in 'user_data' directory.") 71 | } 72 | 73 | func downloadFile(url, filepath string) error { 74 | resp, err := http.Get(url) 75 | if err != nil { 76 | return err 77 | } 78 | defer resp.Body.Close() 79 | 80 | out, err := os.Create(filepath) 81 | if err != nil { 82 | return err 83 | } 84 | defer out.Close() 85 | 86 | _, err = io.Copy(out, resp.Body) 87 | return err 88 | } -------------------------------------------------------------------------------- /src/context_aware_http_server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | // Create a new HTTP server 13 | mux := http.NewServeMux() 14 | mux.HandleFunc("/process", processHandler) 15 | 16 | server := &http.Server{ 17 | Addr: ":8080", 18 | Handler: mux, 19 | } 20 | 21 | // Start the server 22 | log.Println("Server starting on :8080") 23 | if err := server.ListenAndServe(); err != nil { 24 | log.Fatalf("Server failed: %v", err) 25 | } 26 | } 27 | 28 | // processHandler handles the /process endpoint with context-aware processing 29 | func processHandler(w http.ResponseWriter, r *http.Request) { 30 | // Create a context with 5-second timeout 31 | ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) 32 | defer cancel() // Important to avoid context leaks 33 | 34 | // Channel to receive the processing result 35 | resultCh := make(chan string) 36 | 37 | // Start the long-running task in a goroutine 38 | go func() { 39 | resultCh <- longRunningTask(ctx) 40 | }() 41 | 42 | // Wait for either the task to complete or context to be cancelled 43 | select { 44 | case result := <-resultCh: 45 | // Task completed successfully 46 | fmt.Fprintf(w, "Processing completed: %s\n", result) 47 | log.Println("Request completed successfully") 48 | case <-ctx.Done(): 49 | // Context was cancelled (timeout or client disconnect) 50 | err := ctx.Err() 51 | switch err { 52 | case context.DeadlineExceeded: 53 | msg := "Processing cancelled due to timeout" 54 | http.Error(w, msg, http.StatusGatewayTimeout) 55 | log.Println(msg) 56 | case context.Canceled: 57 | msg := "Processing cancelled by client" 58 | http.Error(w, msg, http.StatusBadRequest) 59 | log.Println(msg) 60 | default: 61 | msg := fmt.Sprintf("Processing cancelled: %v", err) 62 | http.Error(w, msg, http.StatusInternalServerError) 63 | log.Println(msg) 64 | } 65 | } 66 | } 67 | 68 | // longRunningTask simulates a task that takes a long time to complete 69 | func longRunningTask(ctx context.Context) string { 70 | log.Println("Long running task started") 71 | 72 | // Simulate work that takes 8 seconds (longer than our timeout) 73 | select { 74 | case <-time.After(2 * time.Second): 75 | return "Task result" 76 | case <-ctx.Done(): 77 | log.Println("Task cancelled:", ctx.Err()) 78 | return "" // This won't be used as context is already done 79 | } 80 | } -------------------------------------------------------------------------------- /src/grpc_exercise/go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 2 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 3 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 4 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 5 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 6 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 7 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 8 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 9 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 10 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 11 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 12 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 13 | go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= 14 | go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= 15 | go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= 16 | go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= 17 | go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= 18 | go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= 19 | go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= 20 | go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= 21 | go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= 22 | go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= 23 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 24 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 25 | golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= 26 | golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 27 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 28 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 29 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= 30 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= 31 | google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= 32 | google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 33 | google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= 34 | google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 35 | -------------------------------------------------------------------------------- /src/car-rental-system/handlers/rental_system_handler.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "car-rental-system/models" 5 | "errors" 6 | "fmt" 7 | "sync" 8 | ) 9 | 10 | type RentalSystem struct { 11 | cars map[int]*models.Car 12 | reservations map[int]*models.Reservation 13 | mu sync.Mutex 14 | reservationID int 15 | } 16 | 17 | func NewRentalSystem() *RentalSystem { 18 | return &RentalSystem{ 19 | cars: make(map[int]*models.Car), 20 | reservations: make(map[int]*models.Reservation), 21 | } 22 | } 23 | 24 | func (rs *RentalSystem) AddCar(car models.Car) { 25 | rs.mu.Lock() 26 | defer rs.mu.Unlock() 27 | rs.cars[car.ID] = &car 28 | } 29 | 30 | func (rs *RentalSystem) SearchCars(make string, maxPrice float64) []models.Car { 31 | rs.mu.Lock() 32 | defer rs.mu.Unlock() 33 | 34 | var results []models.Car 35 | for _, car := range rs.cars { 36 | if car.Make == make && car.RentalPricePerDay <= maxPrice && car.IsAvailable { 37 | results = append(results, *car) 38 | } 39 | } 40 | return results 41 | } 42 | 43 | func (rs *RentalSystem) CreateReservation(customer models.Customer, carID int, startDate, endDate string) (*models.Reservation, error) { 44 | rs.mu.Lock() 45 | defer rs.mu.Unlock() 46 | 47 | car, exists := rs.cars[carID] 48 | if !exists || !car.IsAvailable { 49 | return nil, errors.New("car not available") 50 | } 51 | 52 | rs.reservationID++ 53 | reservation := &models.Reservation{ 54 | ID: rs.reservationID, 55 | Customer: customer, 56 | CarID: carID, 57 | StartDate: startDate, 58 | EndDate: endDate, 59 | TotalPrice: car.RentalPricePerDay, 60 | } 61 | 62 | rs.reservations[rs.reservationID] = reservation 63 | car.IsAvailable = false 64 | 65 | return reservation, nil 66 | } 67 | 68 | func (rs *RentalSystem) ModifyReservation(reservationID int, newStartDate, newEndDate string) error { 69 | rs.mu.Lock() 70 | defer rs.mu.Unlock() 71 | 72 | res, exists := rs.reservations[reservationID] 73 | if !exists { 74 | return errors.New("reservation not found") 75 | } 76 | 77 | res.StartDate = newStartDate 78 | res.EndDate = newEndDate 79 | return nil 80 | } 81 | 82 | func (rs *RentalSystem) ProcessPayment(reservationID int) error { 83 | rs.mu.Lock() 84 | defer rs.mu.Unlock() 85 | 86 | res, exists := rs.reservations[reservationID] 87 | if !exists { 88 | return errors.New("reservation not found") 89 | } 90 | 91 | if res.Paid { 92 | return errors.New("reservation already paid") 93 | } 94 | 95 | res.Paid = true 96 | fmt.Println("Payment processed for reservation ID:", reservationID) 97 | return nil 98 | } 99 | 100 | func (rs *RentalSystem) CancelReservation(reservationID int) error { 101 | rs.mu.Lock() 102 | defer rs.mu.Unlock() 103 | 104 | res, exists := rs.reservations[reservationID] 105 | if !exists { 106 | return errors.New("reservation not found") 107 | } 108 | 109 | if car, exists := rs.cars[res.CarID]; exists { 110 | car.IsAvailable = true 111 | } 112 | 113 | delete(rs.reservations, reservationID) 114 | return nil 115 | } -------------------------------------------------------------------------------- /src/api_exercise/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "errors" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | type book struct { 12 | ID string `json:"id"` 13 | Title string `json:"title"` 14 | Author string `json:"author"` 15 | Quantity int `json:"quantity"` 16 | } 17 | 18 | var books = []book{ 19 | {ID: "1", Title: "In Search of Lost Time", Author: "Marcel Proust", Quantity: 2}, 20 | {ID: "2", Title: "The Great Gatsby", Author: "F. Scott Fitzgerald", Quantity: 5}, 21 | {ID: "3", Title: "War and Peace", Author: "Leo Tolstoy", Quantity: 6}, 22 | } 23 | 24 | func getBooks(c *gin.Context) { 25 | c.IndentedJSON(http.StatusOK, books) 26 | } 27 | 28 | func bookById(c *gin.Context) { 29 | id := c.Param("id") 30 | book, err := getBookById(id) 31 | 32 | if err != nil { 33 | c.IndentedJSON(http.StatusNotFound, gin.H{"message": "Book not found."}) 34 | return 35 | } 36 | 37 | c.IndentedJSON(http.StatusOK, book) 38 | } 39 | 40 | func checkoutBook(c *gin.Context) { 41 | id, ok := c.GetQuery("id") 42 | 43 | if !ok { 44 | c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Missing id query parameter."}) 45 | return 46 | } 47 | 48 | book, err := getBookById(id) 49 | 50 | if err != nil { 51 | c.IndentedJSON(http.StatusNotFound, gin.H{"message": "Book not found."}) 52 | return 53 | } 54 | 55 | if book.Quantity <= 0 { 56 | c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Book not available."}) 57 | return 58 | } 59 | 60 | book.Quantity -= 1 61 | c.IndentedJSON(http.StatusOK, book) 62 | } 63 | 64 | func returnBook(c *gin.Context) { 65 | id, ok := c.GetQuery("id") 66 | 67 | if !ok { 68 | c.IndentedJSON(http.StatusBadRequest, gin.H{"message": "Missing id query parameter."}) 69 | return 70 | } 71 | 72 | book, err := getBookById(id) 73 | 74 | if err != nil { 75 | c.IndentedJSON(http.StatusNotFound, gin.H{"message": "Book not found."}) 76 | return 77 | } 78 | 79 | book.Quantity += 1 80 | c.IndentedJSON(http.StatusOK, book) 81 | } 82 | 83 | func getBookById(id string) (*book, error) { 84 | for i, b := range books { 85 | if b.ID == id { 86 | return &books[i], nil 87 | } 88 | } 89 | 90 | return nil, errors.New("book not found") 91 | } 92 | 93 | func createBook(c *gin.Context) { 94 | var newBook book 95 | 96 | if err := c.BindJSON(&newBook); err != nil { 97 | return 98 | } 99 | 100 | books = append(books, newBook) 101 | c.IndentedJSON(http.StatusCreated, newBook) 102 | } 103 | 104 | func main() { 105 | router := gin.Default() 106 | router.GET("/books", getBooks) 107 | router.GET("/books/:id", bookById) 108 | router.POST("/books", createBook) 109 | router.PATCH("/checkout", checkoutBook) 110 | router.PATCH("/return", returnBook) 111 | router.Run("localhost:8080") 112 | } 113 | //curl -X PATCH "http://localhost:8080/return?id=4" 114 | 115 | //curl -X PATCH "http://localhost:8080/checkout?id=4" 116 | 117 | //curl -X POST http://localhost:8080/books \ 118 | // -H "Content-Type: application/json" \ 119 | // -d '{ 120 | // "id": "4", 121 | // "title": "The ALchemist", 122 | // "author": "Paulo coelho", 123 | // "quantity": 10 124 | // }' 125 | -------------------------------------------------------------------------------- /src/concurrency.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "sync" 9 | ) 10 | 11 | const ( 12 | baseURL = "https://reqres.in/api" 13 | maxConcurrent = 5 14 | ) 15 | 16 | type User struct { 17 | ID int `json:"id"` 18 | Email string `json:"email"` 19 | Name string `json:"first_name"` // Note: reqres.in uses first_name/last_name 20 | } 21 | 22 | type UsersResponse struct { 23 | Data []User `json:"data"` 24 | } 25 | 26 | func listUsers() ([]int, error) { 27 | resp, err := http.Get(baseURL + "/users") 28 | if err != nil { 29 | return nil, fmt.Errorf("failed to make request: %w", err) 30 | } 31 | defer resp.Body.Close() 32 | 33 | if resp.StatusCode != http.StatusOK { 34 | return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) 35 | } 36 | 37 | body, err := io.ReadAll(resp.Body) 38 | if err != nil { 39 | return nil, fmt.Errorf("failed to read response body: %w", err) 40 | } 41 | 42 | var response UsersResponse 43 | if err := json.Unmarshal(body, &response); err != nil { 44 | return nil, fmt.Errorf("failed to unmarshal response: %w", err) 45 | } 46 | 47 | // Extract just the user IDs 48 | var userIds []int 49 | for _, user := range response.Data { 50 | userIds = append(userIds, user.ID) 51 | } 52 | 53 | return userIds, nil 54 | } 55 | 56 | func getUser(userId int, wg *sync.WaitGroup, sem chan struct{}, results chan<- User) { 57 | defer wg.Done() 58 | 59 | // Acquire a semaphore slot 60 | sem <- struct{}{} 61 | defer func() { <-sem }() 62 | 63 | resp, err := http.Get(fmt.Sprintf("%s/users/%d", baseURL, userId)) 64 | if err != nil { 65 | fmt.Printf("Error fetching user %d: %v\n", userId, err) 66 | return 67 | } 68 | defer resp.Body.Close() 69 | 70 | if resp.StatusCode != http.StatusOK { 71 | fmt.Printf("Unexpected status code for user %d: %d\n", userId, resp.StatusCode) 72 | return 73 | } 74 | 75 | body, err := io.ReadAll(resp.Body) 76 | if err != nil { 77 | fmt.Printf("Error reading response for user %d: %v\n", userId, err) 78 | return 79 | } 80 | 81 | var userResponse struct { 82 | Data User `json:"data"` 83 | } 84 | if err := json.Unmarshal(body, &userResponse); err != nil { 85 | fmt.Printf("Error parsing user %d: %v\n", userId, err) 86 | return 87 | } 88 | 89 | results <- userResponse.Data 90 | } 91 | 92 | func main() { 93 | // Step 1: Get list of user IDs 94 | userIds, err := listUsers() 95 | if err != nil { 96 | fmt.Printf("Error listing users: %v\n", err) 97 | return 98 | } 99 | 100 | if len(userIds) == 0 { 101 | fmt.Println("No users found") 102 | return 103 | } 104 | 105 | // Step 2: Fetch each user concurrently with max 5 requests at a time 106 | var wg sync.WaitGroup 107 | sem := make(chan struct{}, maxConcurrent) 108 | results := make(chan User, len(userIds)) 109 | 110 | for _, userId := range userIds { 111 | wg.Add(1) 112 | go getUser(userId, &wg, sem, results) 113 | } 114 | 115 | // Close the results channel when all goroutines are done 116 | go func() { 117 | wg.Wait() 118 | close(results) 119 | }() 120 | 121 | // Collect results 122 | var users []User 123 | for user := range results { 124 | users = append(users, user) 125 | } 126 | 127 | // Print the results 128 | fmt.Printf("\nFetched %d users:\n", len(users)) 129 | for _, user := range users { 130 | fmt.Printf("ID: %d, Name: %s, Email: %s\n", user.ID, user.Name, user.Email) 131 | } 132 | } -------------------------------------------------------------------------------- /src/grpc_exercise/proto/greeter_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.6 5 | // source: proto/greeter.proto 6 | 7 | package greeter 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // GreeterClient is the client API for Greeter service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type GreeterClient interface { 25 | SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) 26 | } 27 | 28 | type greeterClient struct { 29 | cc grpc.ClientConnInterface 30 | } 31 | 32 | func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { 33 | return &greeterClient{cc} 34 | } 35 | 36 | func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { 37 | out := new(HelloReply) 38 | err := c.cc.Invoke(ctx, "/Greeter/SayHello", in, out, opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | return out, nil 43 | } 44 | 45 | // GreeterServer is the server API for Greeter service. 46 | // All implementations must embed UnimplementedGreeterServer 47 | // for forward compatibility 48 | type GreeterServer interface { 49 | SayHello(context.Context, *HelloRequest) (*HelloReply, error) 50 | mustEmbedUnimplementedGreeterServer() 51 | } 52 | 53 | // UnimplementedGreeterServer must be embedded to have forward compatible implementations. 54 | type UnimplementedGreeterServer struct { 55 | } 56 | 57 | func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { 58 | return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") 59 | } 60 | func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} 61 | 62 | // UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. 63 | // Use of this interface is not recommended, as added methods to GreeterServer will 64 | // result in compilation errors. 65 | type UnsafeGreeterServer interface { 66 | mustEmbedUnimplementedGreeterServer() 67 | } 68 | 69 | func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { 70 | s.RegisterService(&Greeter_ServiceDesc, srv) 71 | } 72 | 73 | func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 74 | in := new(HelloRequest) 75 | if err := dec(in); err != nil { 76 | return nil, err 77 | } 78 | if interceptor == nil { 79 | return srv.(GreeterServer).SayHello(ctx, in) 80 | } 81 | info := &grpc.UnaryServerInfo{ 82 | Server: srv, 83 | FullMethod: "/Greeter/SayHello", 84 | } 85 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 86 | return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) 87 | } 88 | return interceptor(ctx, in, info, handler) 89 | } 90 | 91 | // Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. 92 | // It's only intended for direct use with grpc.RegisterService, 93 | // and not to be introspected or modified (even as a copy) 94 | var Greeter_ServiceDesc = grpc.ServiceDesc{ 95 | ServiceName: "Greeter", 96 | HandlerType: (*GreeterServer)(nil), 97 | Methods: []grpc.MethodDesc{ 98 | { 99 | MethodName: "SayHello", 100 | Handler: _Greeter_SayHello_Handler, 101 | }, 102 | }, 103 | Streams: []grpc.StreamDesc{}, 104 | Metadata: "proto/greeter.proto", 105 | } 106 | -------------------------------------------------------------------------------- /src/car_rental_system_refactored.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sync" 7 | ) 8 | 9 | // Car represents a rental car. 10 | type Car struct { 11 | ID int 12 | Make string 13 | Model string 14 | Year int 15 | LicensePlate string 16 | RentalPricePerDay float64 17 | IsAvailable bool 18 | } 19 | 20 | // Customer represents a customer. 21 | type Customer struct { 22 | Name string 23 | ContactDetails string 24 | DriversLicense string 25 | } 26 | 27 | // Reservation holds booking details. 28 | type Reservation struct { 29 | ID int 30 | Customer Customer 31 | CarID int 32 | StartDate string 33 | EndDate string 34 | TotalPrice float64 35 | Paid bool 36 | } 37 | 38 | // RentalSystem manages cars and reservations. 39 | type RentalSystem struct { 40 | cars map[int]*Car 41 | reservations map[int]*Reservation 42 | mu sync.Mutex 43 | reservationID int 44 | } 45 | 46 | // NewRentalSystem initializes the system. 47 | func NewRentalSystem() *RentalSystem { 48 | return &RentalSystem{ 49 | cars: make(map[int]*Car), 50 | reservations: make(map[int]*Reservation), 51 | } 52 | } 53 | 54 | // AddCar adds a car to the system. 55 | func (rs *RentalSystem) AddCar(car Car) { 56 | rs.mu.Lock() 57 | defer rs.mu.Unlock() 58 | rs.cars[car.ID] = &car 59 | } 60 | 61 | // SearchCars returns available cars by criteria. 62 | func (rs *RentalSystem) SearchCars(make string, maxPrice float64) []Car { 63 | rs.mu.Lock() 64 | defer rs.mu.Unlock() 65 | 66 | var results []Car 67 | for _, car := range rs.cars { 68 | if car.Make == make && car.RentalPricePerDay <= maxPrice && car.IsAvailable { 69 | results = append(results, *car) 70 | } 71 | } 72 | return results 73 | } 74 | 75 | // IsCarAvailable checks if a car is free on given dates. 76 | func (rs *RentalSystem) IsCarAvailable(carID int, startDate, endDate string) bool { 77 | for _, res := range rs.reservations { 78 | if res.CarID == carID && res.StartDate <= endDate && res.EndDate >= startDate { 79 | return false 80 | } 81 | } 82 | return true 83 | } 84 | 85 | // CreateReservation books a car. 86 | func (rs *RentalSystem) CreateReservation(customer Customer, carID int, startDate, endDate string) (*Reservation, error) { 87 | rs.mu.Lock() 88 | defer rs.mu.Unlock() 89 | 90 | car, exists := rs.cars[carID] 91 | if !exists || !car.IsAvailable { 92 | return nil, errors.New("car not available") 93 | } 94 | 95 | rs.reservationID++ 96 | reservation := &Reservation{ 97 | ID: rs.reservationID, 98 | Customer: customer, 99 | CarID: carID, 100 | StartDate: startDate, 101 | EndDate: endDate, 102 | TotalPrice: car.RentalPricePerDay, // Assuming one-day reservation 103 | } 104 | 105 | rs.reservations[rs.reservationID] = reservation 106 | car.IsAvailable = false 107 | 108 | return reservation, nil 109 | } 110 | 111 | // ModifyReservation updates reservation dates. 112 | func (rs *RentalSystem) ModifyReservation(reservationID int, newStartDate, newEndDate string) error { 113 | rs.mu.Lock() 114 | defer rs.mu.Unlock() 115 | 116 | res, exists := rs.reservations[reservationID] 117 | if !exists { 118 | return errors.New("reservation not found") 119 | } 120 | 121 | if !rs.IsCarAvailable(res.CarID, newStartDate, newEndDate) { 122 | return errors.New("car not available for new dates") 123 | } 124 | 125 | res.StartDate, res.EndDate = newStartDate, newEndDate 126 | return nil 127 | } 128 | 129 | // CancelReservation removes a reservation. 130 | func (rs *RentalSystem) CancelReservation(reservationID int) error { 131 | rs.mu.Lock() 132 | defer rs.mu.Unlock() 133 | 134 | res, exists := rs.reservations[reservationID] 135 | if !exists { 136 | return errors.New("reservation not found") 137 | } 138 | 139 | if car, exists := rs.cars[res.CarID]; exists { 140 | car.IsAvailable = true 141 | } 142 | 143 | delete(rs.reservations, reservationID) 144 | return nil 145 | } 146 | 147 | // ProcessPayment marks a reservation as paid. 148 | func (rs *RentalSystem) ProcessPayment(reservationID int) error { 149 | rs.mu.Lock() 150 | defer rs.mu.Unlock() 151 | 152 | res, exists := rs.reservations[reservationID] 153 | if !exists { 154 | return errors.New("reservation not found") 155 | } 156 | 157 | if res.Paid { 158 | return errors.New("reservation already paid") 159 | } 160 | 161 | res.Paid = true 162 | fmt.Println("Payment processed for reservation ID:", reservationID) 163 | return nil 164 | } 165 | 166 | // Main function 167 | func main() { 168 | rentalSystem := NewRentalSystem() 169 | 170 | // Adding cars 171 | rentalSystem.AddCar(Car{ID: 1, Make: "Toyota", Model: "Corolla", Year: 2020, LicensePlate: "ABC123", RentalPricePerDay: 50, IsAvailable: true}) 172 | rentalSystem.AddCar(Car{ID: 2, Make: "Honda", Model: "Civic", Year: 2021, LicensePlate: "XYZ789", RentalPricePerDay: 60, IsAvailable: true}) 173 | 174 | // Searching cars 175 | fmt.Println("Available Cars:", rentalSystem.SearchCars("Toyota", 100)) 176 | 177 | // Creating reservation 178 | customer := Customer{Name: "John Doe", ContactDetails: "john.doe@example.com", DriversLicense: "D123456"} 179 | reservation, err := rentalSystem.CreateReservation(customer, 1, "2025-03-29", "2025-03-30") 180 | if err == nil { 181 | fmt.Println("Reservation created:", *reservation) 182 | } 183 | 184 | // Processing payment 185 | if err := rentalSystem.ProcessPayment(reservation.ID); err == nil { 186 | fmt.Println("Payment successful") 187 | } 188 | 189 | // Modifying reservation 190 | if err := rentalSystem.ModifyReservation(reservation.ID, "2025-04-01", "2025-04-02"); err == nil { 191 | fmt.Println("Reservation modified successfully") 192 | } 193 | 194 | // Canceling reservation 195 | if err := rentalSystem.CancelReservation(reservation.ID); err == nil { 196 | fmt.Println("Reservation canceled.") 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/mini_blog.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | "net/http" 7 | "strconv" 8 | "os" 9 | "gorm.io/driver/mysql" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | type BlogPost struct { 14 | ID uint `gorm:"primaryKey" json:"id"` 15 | Title string `gorm:"size:255" json:"title"` 16 | Content string `json:"content"` 17 | Author string `gorm:"size:100" json:"author"` 18 | CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"` 19 | UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at"` 20 | } 21 | 22 | var db *gorm.DB 23 | 24 | func main() { 25 | 26 | dbUser := os.Getenv("DB_USER") 27 | if dbUser == "" { 28 | dbUser = "root" 29 | } 30 | dbPassword := os.Getenv("DB_PASSWORD") 31 | if dbPassword == "" { 32 | dbPassword = "" 33 | } 34 | 35 | dbName := "myDB" 36 | if len(os.Args) > 1 { 37 | dbName = os.Args[1] 38 | } 39 | 40 | dsn := dbUser + ":" + dbPassword + "@tcp(127.0.0.1:3306)/" + dbName + "?charset=utf8mb4&parseTime=True&loc=Local" 41 | 42 | var err error 43 | db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) 44 | if err != nil { 45 | log.Fatal("Failed to connect to database:", err) 46 | } 47 | 48 | // Auto migrate 49 | if err := db.AutoMigrate(&BlogPost{}); err != nil { 50 | log.Fatal("Auto migration failed:", err) 51 | } 52 | 53 | // Set up routes 54 | http.HandleFunc("/posts", postsHandler) 55 | http.HandleFunc("/posts/", postHandler) 56 | http.HandleFunc("/posts/search", searchHandler) 57 | 58 | log.Println("Server running on :8080") 59 | log.Fatal(http.ListenAndServe(":8080", nil)) 60 | } 61 | 62 | func postsHandler(w http.ResponseWriter, r *http.Request) { 63 | switch r.Method { 64 | case http.MethodGet: 65 | getPosts(w, r) 66 | case http.MethodPost: 67 | createPost(w, r) 68 | default: 69 | http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) 70 | } 71 | } 72 | 73 | func postHandler(w http.ResponseWriter, r *http.Request) { 74 | idStr := r.URL.Path[len("/posts/"):] 75 | id, err := strconv.Atoi(idStr) 76 | if err != nil { 77 | http.Error(w, "Invalid ID", http.StatusBadRequest) 78 | return 79 | } 80 | 81 | switch r.Method { 82 | case http.MethodPut: 83 | updatePost(w, r, uint(id)) 84 | case http.MethodDelete: 85 | deletePost(w, r, uint(id)) 86 | default: 87 | http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) 88 | } 89 | } 90 | 91 | func createPost(w http.ResponseWriter, r *http.Request) { 92 | var post BlogPost 93 | if err := json.NewDecoder(r.Body).Decode(&post); err != nil { 94 | http.Error(w, err.Error(), http.StatusBadRequest) 95 | return 96 | } 97 | 98 | if post.Title == "" || post.Content == "" || post.Author == "" { 99 | http.Error(w, "Title, content and author are required", http.StatusBadRequest) 100 | return 101 | } 102 | 103 | if err := db.Create(&post).Error; err != nil { 104 | log.Println("Create error:", err) 105 | http.Error(w, "Failed to create post", http.StatusInternalServerError) 106 | return 107 | } 108 | 109 | log.Println("Created post ID:", post.ID) 110 | w.Header().Set("Content-Type", "application/json") 111 | w.WriteHeader(http.StatusCreated) 112 | json.NewEncoder(w).Encode(post) 113 | } 114 | 115 | func getPosts(w http.ResponseWriter, r *http.Request) { 116 | var posts []BlogPost 117 | if err := db.Find(&posts).Error; err != nil { 118 | log.Println("Get posts error:", err) 119 | http.Error(w, "Failed to get posts", http.StatusInternalServerError) 120 | return 121 | } 122 | 123 | w.Header().Set("Content-Type", "application/json") 124 | json.NewEncoder(w).Encode(posts) 125 | } 126 | 127 | func updatePost(w http.ResponseWriter, r *http.Request, id uint) { 128 | var post BlogPost 129 | if err := db.First(&post, id).Error; err != nil { 130 | log.Println("Update find error:", err) 131 | http.Error(w, "Post not found", http.StatusNotFound) 132 | return 133 | } 134 | 135 | var updateData struct { 136 | Title string `json:"title"` 137 | Content string `json:"content"` 138 | } 139 | if err := json.NewDecoder(r.Body).Decode(&updateData); err != nil { 140 | http.Error(w, err.Error(), http.StatusBadRequest) 141 | return 142 | } 143 | 144 | if updateData.Title == "" || updateData.Content == "" { 145 | http.Error(w, "Title and content are required", http.StatusBadRequest) 146 | return 147 | } 148 | 149 | post.Title = updateData.Title 150 | post.Content = updateData.Content 151 | 152 | if err := db.Save(&post).Error; err != nil { 153 | log.Println("Update save error:", err) 154 | http.Error(w, "Failed to update post", http.StatusInternalServerError) 155 | return 156 | } 157 | 158 | log.Println("Updated post ID:", id) 159 | w.Header().Set("Content-Type", "application/json") 160 | json.NewEncoder(w).Encode(post) 161 | } 162 | 163 | func deletePost(w http.ResponseWriter, r *http.Request, id uint) { 164 | if err := db.Delete(&BlogPost{}, id).Error; err != nil { 165 | log.Println("Delete error:", err) 166 | http.Error(w, "Failed to delete post", http.StatusInternalServerError) 167 | return 168 | } 169 | log.Println("Deleted post ID:", id) 170 | w.Header().Set("Content-Type", "application/json") 171 | json.NewEncoder(w).Encode(map[string]string{"message": "Post deleted"}) 172 | } 173 | 174 | func searchHandler(w http.ResponseWriter, r *http.Request) { 175 | if r.Method != http.MethodGet { 176 | http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) 177 | return 178 | } 179 | 180 | title := r.URL.Query().Get("title") 181 | author := r.URL.Query().Get("author") 182 | 183 | var posts []BlogPost 184 | query := db 185 | 186 | if title != "" { 187 | query = query.Where("title LIKE ?", "%"+title+"%") 188 | } 189 | if author != "" { 190 | query = query.Where("author LIKE ?", "%"+author+"%") 191 | } 192 | 193 | if err := query.Find(&posts).Error; err != nil { 194 | log.Println("Search error:", err) 195 | http.Error(w, "Failed to search posts", http.StatusInternalServerError) 196 | return 197 | } 198 | 199 | w.Header().Set("Content-Type", "application/json") 200 | json.NewEncoder(w).Encode(posts) 201 | } -------------------------------------------------------------------------------- /src/car_rental_system.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sync" 7 | ) 8 | 9 | // Struct to represent a Car 10 | type Car struct { 11 | ID int 12 | Make string 13 | Model string 14 | Year int 15 | LicensePlate string 16 | RentalPricePerDay float64 17 | IsAvailable bool 18 | } 19 | 20 | // Struct to represent a Customer 21 | type Customer struct { 22 | Name string 23 | ContactDetails string 24 | DriversLicense string 25 | } 26 | 27 | // Struct to represent a Reservation 28 | type Reservation struct { 29 | ID int 30 | Customer Customer 31 | CarID int 32 | StartDate string 33 | EndDate string 34 | TotalPrice float64 35 | Paid bool 36 | } 37 | 38 | // RentalSystem struct to manage the entire system 39 | type RentalSystem struct { 40 | Cars []Car 41 | Reservations []Reservation 42 | mu sync.Mutex 43 | reservationID int 44 | } 45 | 46 | // AddCar adds a new car to the system 47 | func (rs *RentalSystem) AddCar(car Car) { 48 | rs.mu.Lock() 49 | defer rs.mu.Unlock() 50 | rs.Cars = append(rs.Cars, car) 51 | } 52 | 53 | // SearchCars searches for cars based on criteria 54 | func (rs *RentalSystem) SearchCars(carType string, maxPrice float64) []Car { 55 | rs.mu.Lock() 56 | defer rs.mu.Unlock() 57 | 58 | var results []Car 59 | for _, car := range rs.Cars { 60 | if car.Make == carType && car.RentalPricePerDay <= maxPrice && car.IsAvailable { 61 | results = append(results, car) 62 | } 63 | } 64 | return results 65 | } 66 | 67 | func (rs *RentalSystem) IsCarAvailable(carID int, startDate, endDate string) bool { 68 | for _, res := range rs.Reservations { 69 | if res.CarID == carID && res.StartDate <= endDate && res.EndDate >= startDate { 70 | return false 71 | } 72 | } 73 | return true 74 | } 75 | 76 | // CreateReservation creates a new reservation 77 | func (rs *RentalSystem) CreateReservation(customer Customer, carID int, startDate, endDate string) (Reservation, error) { 78 | rs.mu.Lock() 79 | defer rs.mu.Unlock() 80 | 81 | for i, car := range rs.Cars { 82 | if car.ID == carID && car.IsAvailable { 83 | rs.reservationID++ 84 | totalPrice := car.RentalPricePerDay // Assuming only one day for simplicity 85 | reservation := Reservation{ 86 | ID: rs.reservationID, 87 | Customer: customer, 88 | CarID: carID, 89 | StartDate: startDate, 90 | EndDate: endDate, 91 | TotalPrice: totalPrice, 92 | } 93 | rs.Reservations = append(rs.Reservations, reservation) 94 | rs.Cars[i].IsAvailable = false 95 | return reservation, nil 96 | } 97 | } 98 | return Reservation{}, errors.New("car not available") 99 | } 100 | 101 | func (rs *RentalSystem) ModifyReservation(reservationID int, newStartDate, newEndDate string) error { 102 | rs.mu.Lock() 103 | defer rs.mu.Unlock() 104 | 105 | for i, res := range rs.Reservations { 106 | if res.ID == reservationID { 107 | if rs.IsCarAvailable(res.CarID, newStartDate, newEndDate) { 108 | rs.Reservations[i].StartDate = newStartDate 109 | rs.Reservations[i].EndDate = newEndDate 110 | return nil 111 | } 112 | return errors.New("car not available for new dates") 113 | } 114 | } 115 | return errors.New("reservation not found") 116 | } 117 | 118 | // CancelReservation cancels an existing reservation 119 | func (rs *RentalSystem) CancelReservation(reservationID int) error { 120 | rs.mu.Lock() 121 | defer rs.mu.Unlock() 122 | 123 | for i, res := range rs.Reservations { 124 | if res.ID == reservationID { 125 | // Make car available again 126 | for j, car := range rs.Cars { 127 | if car.ID == res.CarID { 128 | rs.Cars[j].IsAvailable = true 129 | break 130 | } 131 | } 132 | // Remove reservation 133 | rs.Reservations = append(rs.Reservations[:i], rs.Reservations[i+1:]...) 134 | return nil 135 | } 136 | } 137 | return errors.New("reservation not found") 138 | } 139 | 140 | func (rs *RentalSystem) ProcessPayment(reservationID int) error { 141 | rs.mu.Lock() 142 | defer rs.mu.Unlock() 143 | 144 | for i, res := range rs.Reservations { 145 | if res.ID == reservationID { 146 | if rs.Reservations[i].Paid { 147 | return errors.New("reservation already paid") 148 | } 149 | rs.Reservations[i].Paid = true 150 | fmt.Println("Payment processed successfully for reservation ID:", reservationID) 151 | return nil 152 | } 153 | } 154 | return errors.New("reservation not found") 155 | } 156 | 157 | // Main function 158 | func main() { 159 | rentalSystem := &RentalSystem{} 160 | 161 | // Adding cars to the system 162 | rentalSystem.AddCar(Car{ID: 1, Make: "Toyota", Model: "Corolla", Year: 2020, LicensePlate: "ABC123", RentalPricePerDay: 50, IsAvailable: true}) 163 | rentalSystem.AddCar(Car{ID: 2, Make: "Honda", Model: "Civic", Year: 2021, LicensePlate: "XYZ789", RentalPricePerDay: 60, IsAvailable: true}) 164 | 165 | // Searching for available cars 166 | availableCars := rentalSystem.SearchCars("Toyota", 100) 167 | fmt.Println("Available Cars:", availableCars) 168 | 169 | // Creating a reservation 170 | customer := Customer{Name: "John Doe", ContactDetails: "john.doe@example.com", DriversLicense: "D123456"} 171 | reservation, err := rentalSystem.CreateReservation(customer, 1, "2025-03-29", "2025-03-30") 172 | if err != nil { 173 | fmt.Println("Error creating reservation:", err) 174 | } else { 175 | fmt.Println("Reservation created:", reservation) 176 | } 177 | 178 | // process payment 179 | err = rentalSystem.ProcessPayment(reservation.ID) 180 | if err != nil { 181 | fmt.Println("Payment error:", err) 182 | } 183 | 184 | // Modify reservation 185 | err = rentalSystem.ModifyReservation(reservation.ID, "2025-04-01", "2025-04-02") 186 | if err != nil { 187 | fmt.Println("Modification error:", err) 188 | } else { 189 | fmt.Println("Reservation modified successfully.") 190 | } 191 | 192 | // Canceling a reservation 193 | err = rentalSystem.CancelReservation(reservation.ID) 194 | if err != nil { 195 | fmt.Println("Error canceling reservation:", err) 196 | } else { 197 | fmt.Println("Reservation canceled.") 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/api_exercise/go.sum: -------------------------------------------------------------------------------- 1 | github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= 2 | github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= 3 | github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= 4 | github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= 5 | github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= 6 | github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= 7 | github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= 8 | github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= 9 | github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= 10 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 | github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= 13 | github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= 14 | github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= 15 | github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= 16 | github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= 17 | github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= 18 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 19 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 20 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 21 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 22 | github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= 23 | github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= 24 | github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= 25 | github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= 26 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 27 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 28 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 29 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 30 | github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= 31 | github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= 32 | github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= 33 | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= 34 | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 35 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 36 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 37 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 38 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 39 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 40 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 41 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 42 | github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= 43 | github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= 44 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 45 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 46 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 47 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 48 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 49 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 50 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 51 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 52 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 53 | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= 54 | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= 55 | github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= 56 | github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= 57 | golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U= 58 | golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= 59 | golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= 60 | golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= 61 | golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= 62 | golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= 63 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 64 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 65 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 66 | golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= 67 | golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= 68 | google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 69 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 70 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 71 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 72 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 73 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 74 | nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= 75 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 76 | -------------------------------------------------------------------------------- /src/grpc_exercise/proto/greeter.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc v3.19.6 5 | // source: proto/greeter.proto 6 | 7 | package greeter 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type HelloRequest struct { 24 | state protoimpl.MessageState 25 | sizeCache protoimpl.SizeCache 26 | unknownFields protoimpl.UnknownFields 27 | 28 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 29 | } 30 | 31 | func (x *HelloRequest) Reset() { 32 | *x = HelloRequest{} 33 | if protoimpl.UnsafeEnabled { 34 | mi := &file_proto_greeter_proto_msgTypes[0] 35 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 36 | ms.StoreMessageInfo(mi) 37 | } 38 | } 39 | 40 | func (x *HelloRequest) String() string { 41 | return protoimpl.X.MessageStringOf(x) 42 | } 43 | 44 | func (*HelloRequest) ProtoMessage() {} 45 | 46 | func (x *HelloRequest) ProtoReflect() protoreflect.Message { 47 | mi := &file_proto_greeter_proto_msgTypes[0] 48 | if protoimpl.UnsafeEnabled && x != nil { 49 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 50 | if ms.LoadMessageInfo() == nil { 51 | ms.StoreMessageInfo(mi) 52 | } 53 | return ms 54 | } 55 | return mi.MessageOf(x) 56 | } 57 | 58 | // Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead. 59 | func (*HelloRequest) Descriptor() ([]byte, []int) { 60 | return file_proto_greeter_proto_rawDescGZIP(), []int{0} 61 | } 62 | 63 | func (x *HelloRequest) GetName() string { 64 | if x != nil { 65 | return x.Name 66 | } 67 | return "" 68 | } 69 | 70 | type HelloReply struct { 71 | state protoimpl.MessageState 72 | sizeCache protoimpl.SizeCache 73 | unknownFields protoimpl.UnknownFields 74 | 75 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 76 | } 77 | 78 | func (x *HelloReply) Reset() { 79 | *x = HelloReply{} 80 | if protoimpl.UnsafeEnabled { 81 | mi := &file_proto_greeter_proto_msgTypes[1] 82 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 83 | ms.StoreMessageInfo(mi) 84 | } 85 | } 86 | 87 | func (x *HelloReply) String() string { 88 | return protoimpl.X.MessageStringOf(x) 89 | } 90 | 91 | func (*HelloReply) ProtoMessage() {} 92 | 93 | func (x *HelloReply) ProtoReflect() protoreflect.Message { 94 | mi := &file_proto_greeter_proto_msgTypes[1] 95 | if protoimpl.UnsafeEnabled && x != nil { 96 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 97 | if ms.LoadMessageInfo() == nil { 98 | ms.StoreMessageInfo(mi) 99 | } 100 | return ms 101 | } 102 | return mi.MessageOf(x) 103 | } 104 | 105 | // Deprecated: Use HelloReply.ProtoReflect.Descriptor instead. 106 | func (*HelloReply) Descriptor() ([]byte, []int) { 107 | return file_proto_greeter_proto_rawDescGZIP(), []int{1} 108 | } 109 | 110 | func (x *HelloReply) GetMessage() string { 111 | if x != nil { 112 | return x.Message 113 | } 114 | return "" 115 | } 116 | 117 | var File_proto_greeter_proto protoreflect.FileDescriptor 118 | 119 | var file_proto_greeter_proto_rawDesc = []byte{ 120 | 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x2e, 121 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 122 | 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 123 | 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 124 | 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 125 | 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 126 | 0x65, 0x32, 0x33, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x08, 127 | 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x0d, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 128 | 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 129 | 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x3b, 0x67, 0x72, 0x65, 0x65, 130 | 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 131 | } 132 | 133 | var ( 134 | file_proto_greeter_proto_rawDescOnce sync.Once 135 | file_proto_greeter_proto_rawDescData = file_proto_greeter_proto_rawDesc 136 | ) 137 | 138 | func file_proto_greeter_proto_rawDescGZIP() []byte { 139 | file_proto_greeter_proto_rawDescOnce.Do(func() { 140 | file_proto_greeter_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_greeter_proto_rawDescData) 141 | }) 142 | return file_proto_greeter_proto_rawDescData 143 | } 144 | 145 | var file_proto_greeter_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 146 | var file_proto_greeter_proto_goTypes = []interface{}{ 147 | (*HelloRequest)(nil), // 0: HelloRequest 148 | (*HelloReply)(nil), // 1: HelloReply 149 | } 150 | var file_proto_greeter_proto_depIdxs = []int32{ 151 | 0, // 0: Greeter.SayHello:input_type -> HelloRequest 152 | 1, // 1: Greeter.SayHello:output_type -> HelloReply 153 | 1, // [1:2] is the sub-list for method output_type 154 | 0, // [0:1] is the sub-list for method input_type 155 | 0, // [0:0] is the sub-list for extension type_name 156 | 0, // [0:0] is the sub-list for extension extendee 157 | 0, // [0:0] is the sub-list for field type_name 158 | } 159 | 160 | func init() { file_proto_greeter_proto_init() } 161 | func file_proto_greeter_proto_init() { 162 | if File_proto_greeter_proto != nil { 163 | return 164 | } 165 | if !protoimpl.UnsafeEnabled { 166 | file_proto_greeter_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 167 | switch v := v.(*HelloRequest); i { 168 | case 0: 169 | return &v.state 170 | case 1: 171 | return &v.sizeCache 172 | case 2: 173 | return &v.unknownFields 174 | default: 175 | return nil 176 | } 177 | } 178 | file_proto_greeter_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 179 | switch v := v.(*HelloReply); i { 180 | case 0: 181 | return &v.state 182 | case 1: 183 | return &v.sizeCache 184 | case 2: 185 | return &v.unknownFields 186 | default: 187 | return nil 188 | } 189 | } 190 | } 191 | type x struct{} 192 | out := protoimpl.TypeBuilder{ 193 | File: protoimpl.DescBuilder{ 194 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 195 | RawDescriptor: file_proto_greeter_proto_rawDesc, 196 | NumEnums: 0, 197 | NumMessages: 2, 198 | NumExtensions: 0, 199 | NumServices: 1, 200 | }, 201 | GoTypes: file_proto_greeter_proto_goTypes, 202 | DependencyIndexes: file_proto_greeter_proto_depIdxs, 203 | MessageInfos: file_proto_greeter_proto_msgTypes, 204 | }.Build() 205 | File_proto_greeter_proto = out.File 206 | file_proto_greeter_proto_rawDesc = nil 207 | file_proto_greeter_proto_goTypes = nil 208 | file_proto_greeter_proto_depIdxs = nil 209 | } 210 | --------------------------------------------------------------------------------