From 0e296146ecce2c92137165a2388c3006bf888099 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 06:28:32 +0000 Subject: [PATCH 01/23] inventory solution --- go/01-basics/inventory.go | 81 ++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/go/01-basics/inventory.go b/go/01-basics/inventory.go index 209c374..52694e2 100644 --- a/go/01-basics/inventory.go +++ b/go/01-basics/inventory.go @@ -1,40 +1,101 @@ package main +import "fmt" + +type Category int + +const ( + Electronics Category = iota + Groceries + Clothes +) + +func (c Category) String() string { + switch c { + case Electronics: + return "Electronics" + case Groceries: + return "Groceries" + case Clothes: + return "Clothes" + default: + return "Unknown" + } +} + +// Struct for product details type Product struct { Name string Price float64 Quantity int - Category string //TODO: use enum instead + Category Category } -func addProduct(inventory *[]Product, name string, price float64, quantity int, category string) { - //TODO: implement +// Add a new product to the inventory +func addProduct(inventory *[]Product, name string, price float64, quantity int, category Category) { + // Check if the product already exists in the inventory + for _, product := range *inventory { + if product.Name == name { + fmt.Println("Product already exists.") + return + } + } + // Add the new product + *inventory = append(*inventory, Product{ + Name: name, + Price: price, + Quantity: quantity, + Category: category, + }) + fmt.Printf("Added product: %s\n", name) } +// Remove a product from the inventory func removeProduct(inventory *[]Product, name string) { - //TODO: implement + for i, product := range *inventory { + if product.Name == name { + *inventory = append((*inventory)[:i], (*inventory)[i+1:]...) + fmt.Printf("Removed product: %s\n", name) + return + } + } + fmt.Println("Product not found.") } +// Update the quantity of a product func updateQuantity(inventory *[]Product, name string, newQuantity int) { - //TODO: implement + for i, product := range *inventory { + if product.Name == name { + (*inventory)[i].Quantity = newQuantity + fmt.Printf("Updated quantity for %s: New Quantity = %d\n", name, newQuantity) + return + } + } + fmt.Println("Product not found.") } +// Display the inventory func displayInventory(inventory []Product) { - //TODO: implement + fmt.Println("Inventory:") + for _, product := range inventory { + fmt.Printf("%s - %s (Price: $%.2f, Quantity: %d)\n", + product.Name, product.Category, product.Price, product.Quantity) + } } func main() { + // Initialize inventory inventory := []Product{ - {Name: "Laptop", Price: 1000, Quantity: 5, Category: "Electronics"}, - {Name: "Apples", Price: 2, Quantity: 50, Category: "Groceries"}, - {Name: "T-shirt", Price: 10, Quantity: 20, Category: "Clothes"}, + {Name: "Laptop", Price: 1000, Quantity: 5, Category: Electronics}, + {Name: "Apples", Price: 2, Quantity: 50, Category: Groceries}, + {Name: "T-shirt", Price: 10, Quantity: 20, Category: Clothes}, } // Display initial inventory displayInventory(inventory) // Add a new product - addProduct(&inventory, "Phone", 800, 10, "Electronics") + addProduct(&inventory, "Phone", 800, 10, Electronics) // Display updated inventory displayInventory(inventory) From c4743195e9c7c9a86ac96f728bb4d823cc3441f2 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:03:40 +0000 Subject: [PATCH 02/23] methods --- go/02-next-level/00-methods.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 go/02-next-level/00-methods.go diff --git a/go/02-next-level/00-methods.go b/go/02-next-level/00-methods.go new file mode 100644 index 0000000..a005976 --- /dev/null +++ b/go/02-next-level/00-methods.go @@ -0,0 +1,24 @@ +package main + +import "fmt" + +type Counter struct { + value int +} + +// pointer receiver +func (c *Counter) Increment() { + c.value++ +} + +// value receiver +func (c Counter) String() string { + return fmt.Sprintf("Counter value: %d", c.value) +} + +func main() { + c := Counter{} + fmt.Println(c) + c.Increment() + fmt.Println(c) +} From 8c82494c252518150ce00ef400eebf32e9e9b0c3 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:03:55 +0000 Subject: [PATCH 03/23] interfaces --- go/02-next-level/01-interfaces.go | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 go/02-next-level/01-interfaces.go diff --git a/go/02-next-level/01-interfaces.go b/go/02-next-level/01-interfaces.go new file mode 100644 index 0000000..6a6e25f --- /dev/null +++ b/go/02-next-level/01-interfaces.go @@ -0,0 +1,60 @@ +package main + +import ( + "fmt" + "math" +) + +type geometry interface { + area() float64 + perim() float64 +} + +type rect struct { + width, height float64 +} + +var _ geometry = rect{} + +type circle struct { + radius float64 +} + +var _ geometry = circle{} + +func (r rect) area() float64 { + return r.width * r.height +} +func (r rect) perim() float64 { + return 2*r.width + 2*r.height +} + +func (c circle) area() float64 { + return math.Pi * c.radius * c.radius +} +func (c circle) perim() float64 { + return 2 * math.Pi * c.radius +} + +func measure(g geometry) { + fmt.Println(g) + fmt.Println(g.area()) + fmt.Println(g.perim()) +} + +func detectCircle(g geometry) { + if c, ok := g.(circle); ok { + fmt.Println("circle with radius", c.radius) + } +} + +func main() { + r := rect{width: 3, height: 4} + c := circle{radius: 5} + + measure(r) + measure(c) + + detectCircle(r) + detectCircle(c) +} From bc3bb55be27ed05d9dc2cf6506edb94f6c1adb65 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:04:05 +0000 Subject: [PATCH 04/23] struct embedding --- go/02-next-level/02-struct-embedding.go | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 go/02-next-level/02-struct-embedding.go diff --git a/go/02-next-level/02-struct-embedding.go b/go/02-next-level/02-struct-embedding.go new file mode 100644 index 0000000..72f46fd --- /dev/null +++ b/go/02-next-level/02-struct-embedding.go @@ -0,0 +1,40 @@ +package main + +import "fmt" + +type Person struct { + Name string +} + +func (p Person) Say() { + fmt.Println("Hi, my name is", p.Name) +} + +type Student struct { + Person + Semester int +} + +type Teacher struct { + Person + Subject string +} + +func main() { + + max := Person{"Max"} + + daniel := Student{Person{"Daniel"}, 3} + + sebastian := Teacher{Person{"Sebastian"}, "PR3"} + + max.Say() + + daniel.Say() + + sebastian.Say() + + max = sebastian.Person + + max.Say() +} From 473564d279064f2387e5c4372a7f39d6a3db67a2 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:04:08 +0000 Subject: [PATCH 05/23] errors --- go/02-next-level/03-errors.go | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 go/02-next-level/03-errors.go diff --git a/go/02-next-level/03-errors.go b/go/02-next-level/03-errors.go new file mode 100644 index 0000000..983549b --- /dev/null +++ b/go/02-next-level/03-errors.go @@ -0,0 +1,55 @@ +package main + +import ( + "errors" + "fmt" +) + +func f(arg int) (int, error) { + if arg == 42 { + + return -1, errors.New("can't work with 42") + } + + return arg + 3, nil +} + +var ErrOutOfTea = fmt.Errorf("no more tea available") +var ErrPower = fmt.Errorf("can't boil water") + +func makeTea(arg int) error { + if arg == 2 { + return ErrOutOfTea + } else if arg == 4 { + + return fmt.Errorf("making tea: %w", ErrPower) + } + return nil +} + +func main() { + for _, i := range []int{7, 42} { + + if r, e := f(i); e != nil { + fmt.Println("f failed:", e) + } else { + fmt.Println("f worked:", r) + } + } + + for i := range 5 { + if err := makeTea(i); err != nil { + + if errors.Is(err, ErrOutOfTea) { + fmt.Println("We should buy new tea!") + } else if errors.Is(err, ErrPower) { + fmt.Println("Now it is dark.") + } else { + fmt.Printf("unknown error: %s\n", err) + } + continue + } + + fmt.Println("Tea is ready!") + } +} From 28961af49961a79c2b3fcec229ab00b8c2adaf35 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:04:14 +0000 Subject: [PATCH 06/23] closure --- go/02-next-level/04-closure.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 go/02-next-level/04-closure.go diff --git a/go/02-next-level/04-closure.go b/go/02-next-level/04-closure.go new file mode 100644 index 0000000..f057a03 --- /dev/null +++ b/go/02-next-level/04-closure.go @@ -0,0 +1,23 @@ +package main + +import "fmt" + +func intSeq() func() int { + i := 0 + return func() int { + i++ + return i + } +} + +func main() { + + nextInt := intSeq() + + fmt.Println(nextInt()) + fmt.Println(nextInt()) + fmt.Println(nextInt()) + + newInts := intSeq() + fmt.Println(newInts()) +} From 9d4efc7138a2f5f583cc5165e9fa1cdd037b94e1 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:04:27 +0000 Subject: [PATCH 07/23] generics --- go/02-next-level/05-generics.go | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/go/02-next-level/05-generics.go b/go/02-next-level/05-generics.go index 5481cb1..09fe044 100644 --- a/go/02-next-level/05-generics.go +++ b/go/02-next-level/05-generics.go @@ -2,7 +2,7 @@ package main import "fmt" -func SlicesIndex[S []E, E int](s []string, v string) int { +func SlicesIndex[S []E, E comparable](s S, v E) int { for i := range s { if v == s[i] { return i @@ -11,27 +11,27 @@ func SlicesIndex[S []E, E int](s []string, v string) int { return -1 } -type List struct { - head, tail *element +type List[T any] struct { + head, tail *element[T] } -type element struct { - next *element - val int +type element[T any] struct { + next *element[T] + val T } -func (lst *List) Push(v int) { +func (lst *List[T]) Push(v T) { if lst.tail == nil { - lst.head = &element{val: v} + lst.head = &element[T]{val: v} lst.tail = lst.head } else { - lst.tail.next = &element{val: v} + lst.tail.next = &element[T]{val: v} lst.tail = lst.tail.next } } -func (lst *List) AllElements() []int { - var elems []int +func (lst *List[T]) AllElements() []T { + var elems []T for e := lst.head; e != nil; e = e.next { elems = append(elems, e.val) } @@ -40,12 +40,17 @@ func (lst *List) AllElements() []int { func main() { var s = []string{"foo", "bar", "zoo"} - fmt.Println("index of zoo:", SlicesIndex(s, "zoo")) - lst := List{} + _ = SlicesIndex[[]string, string](s, "zoo") + + var s2 = []int{2, 4, 5, 6} + fmt.Println("index of 4: ", SlicesIndex(s2, 4)) + + lst := List[float64]{} lst.Push(10) lst.Push(13) lst.Push(23) + lst.Push(23.3) fmt.Println("list:", lst.AllElements()) } From 687f9949f4844ec9e3986a78d1f8e2db15bc156d Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:04:38 +0000 Subject: [PATCH 08/23] defer --- go/02-next-level/06-defer.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go/02-next-level/06-defer.go b/go/02-next-level/06-defer.go index 998103c..fde5ef5 100644 --- a/go/02-next-level/06-defer.go +++ b/go/02-next-level/06-defer.go @@ -6,9 +6,10 @@ import ( ) func main() { + f := createFile("/tmp/defer.txt") + defer closeFile(f) writeFile(f) - closeFile(f) } func createFile(p string) *os.File { From a15c5c65383f14c502930438c19e89bf3efa8499 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 09:20:37 +0000 Subject: [PATCH 09/23] implement myMath module --- go/03-modules/go.mod | 5 +++++ go/03-modules/go.sum | 2 ++ go/03-modules/main.go | 16 +++++++++++++- go/03-modules/myMath/math_test.go | 35 +++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 go/03-modules/go.mod create mode 100644 go/03-modules/go.sum create mode 100644 go/03-modules/myMath/math_test.go diff --git a/go/03-modules/go.mod b/go/03-modules/go.mod new file mode 100644 index 0000000..b93913c --- /dev/null +++ b/go/03-modules/go.mod @@ -0,0 +1,5 @@ +module gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath + +go 1.25.0 + +require github.com/google/uuid v1.6.0 diff --git a/go/03-modules/go.sum b/go/03-modules/go.sum new file mode 100644 index 0000000..7790d7c --- /dev/null +++ b/go/03-modules/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/go/03-modules/main.go b/go/03-modules/main.go index 7905807..ab01282 100644 --- a/go/03-modules/main.go +++ b/go/03-modules/main.go @@ -1,5 +1,19 @@ package main -func main() { +import ( + "fmt" + mm "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + //_ "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + + "github.com/google/uuid" + //run go get github.com/google/uuid + //or go mod tidy => go.sum +) + +func main() { + fmt.Println(mm.Add(1, 2)) + + id := uuid.New() + fmt.Println("Generated UUID:", id) } diff --git a/go/03-modules/myMath/math_test.go b/go/03-modules/myMath/math_test.go new file mode 100644 index 0000000..cf3fe11 --- /dev/null +++ b/go/03-modules/myMath/math_test.go @@ -0,0 +1,35 @@ +package myMath_test + +import ( + "testing" + + "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" +) + +func TestAdd(t *testing.T) { + sum := myMath.Add(2, 3) + if sum != 5 { + t.Errorf("Add(2,3) = %v, want %v", sum, 5) + } +} + +func TestMin(t *testing.T) { + type args struct { + in0 int + in1 int + } + tests := []struct { + name string + args args + want int + }{ + {"first greater", args{3, 2}, 2}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := myMath.Min(tt.args.in0, tt.args.in1); got != tt.want { + t.Errorf("Min() = %v, want %v", got, tt.want) + } + }) + } +} From 0f90d8f25bb6ceeec8a9d4a434aecfa87b2dc428 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 09:20:59 +0000 Subject: [PATCH 10/23] implement myMath module II --- go/03-modules/myMath/math.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/go/03-modules/myMath/math.go b/go/03-modules/myMath/math.go index e69de29..de9b318 100644 --- a/go/03-modules/myMath/math.go +++ b/go/03-modules/myMath/math.go @@ -0,0 +1,23 @@ +package myMath + +import "fmt" + +func init() { + fmt.Println("initializing myMath") +} + +func Add(a, b int) int { + return a + b +} + +func greater(a, b int) bool { + return a > b +} + +func Min(a, b int) int { + if greater(a, b) { + return b + } else { + return a + } +} From 50100a303571379c5d84f71295c1dac3b3ef22e2 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 11:13:53 +0000 Subject: [PATCH 11/23] fix go.mod --- go/03-modules/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/03-modules/go.mod b/go/03-modules/go.mod index b93913c..e56e608 100644 --- a/go/03-modules/go.mod +++ b/go/03-modules/go.mod @@ -1,4 +1,4 @@ -module gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath +module gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules go 1.25.0 From 06b2a21660a53bb914c6da455584b3afed445495 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 07:10:26 +0000 Subject: [PATCH 12/23] modules starting point --- go/03-modules/main.go | 5 +++++ go/03-modules/myMath/math.go | 0 2 files changed, 5 insertions(+) create mode 100644 go/03-modules/main.go create mode 100644 go/03-modules/myMath/math.go diff --git a/go/03-modules/main.go b/go/03-modules/main.go new file mode 100644 index 0000000..7905807 --- /dev/null +++ b/go/03-modules/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + +} diff --git a/go/03-modules/myMath/math.go b/go/03-modules/myMath/math.go new file mode 100644 index 0000000..e69de29 From b4764e03144fc21d931d494de745415ff90b2bb7 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 09:18:14 +0000 Subject: [PATCH 13/23] fix go mod tidy permission issues --- go/.devcontainer/Dockerfile | 17 ++++++++++++----- go/.devcontainer/devcontainer.json | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/go/.devcontainer/Dockerfile b/go/.devcontainer/Dockerfile index 506077c..206f58f 100644 --- a/go/.devcontainer/Dockerfile +++ b/go/.devcontainer/Dockerfile @@ -1,14 +1,21 @@ FROM golang:1.25 RUN apt-get update && apt-get install -y build-essential -RUN go install github.com/go-delve/delve/cmd/dlv@latest -RUN go install -v github.com/cweill/gotests/gotests@v1.6.0 -RUN go install -v golang.org/x/tools/gopls@latest -RUN go install -v golang.org/x/tools/cmd/goimports@latest -RUN go install -v honnef.co/go/tools/cmd/staticcheck@latest + +#RUN go install github.com/go-delve/delve/cmd/dlv@latest +#RUN go install github.com/cweill/gotests/gotests@v1.6.0 +#RUN go install golang.org/x/tools/gopls@latest +#RUN go install golang.org/x/tools/cmd/goimports@latest +#RUN go install honnef.co/go/tools/cmd/staticcheck@latest + +# allow all users to add go packages in that container +#RUN mkdir -p /go/pkg && chmod -R a+rwx /go/pkg +#RUN chmod -R a+rwx /go/pkg/mod /go/pkg/sumdb +#RUN chmod -R a+rwx /go/pkg/mod/github.com ARG USERNAME=developer ARG USER_UID=1000 ARG USER_GID=$USER_UID RUN groupadd --gid $USER_GID $USERNAME && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME USER $USERNAME + diff --git a/go/.devcontainer/devcontainer.json b/go/.devcontainer/devcontainer.json index 6dae661..3f36777 100644 --- a/go/.devcontainer/devcontainer.json +++ b/go/.devcontainer/devcontainer.json @@ -3,7 +3,8 @@ "build": { "dockerfile": "Dockerfile" }, - "customizations": { + "postCreateCommand": "go install github.com/go-delve/delve/cmd/dlv@latest && go install github.com/cweill/gotests/gotests@v1.6.0 && go install golang.org/x/tools/gopls@latest && go install golang.org/x/tools/cmd/goimports@latest && go install honnef.co/go/tools/cmd/staticcheck@latest", + "customizations": { "vscode": { "extensions": [ "golang.go", "gruntfuggly.todo-tree" From 592f15c5b12bb25f8a08aa99c05460da68a5ea86 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 11:22:18 +0000 Subject: [PATCH 14/23] design pattern assignment --- go/04-design-pattern/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 go/04-design-pattern/README.md diff --git a/go/04-design-pattern/README.md b/go/04-design-pattern/README.md new file mode 100644 index 0000000..850d97c --- /dev/null +++ b/go/04-design-pattern/README.md @@ -0,0 +1,9 @@ +# Assignment + +Implement an arbitrary [design pattern](https://refactoring.guru/design-patterns/catalog) in Go. + +1. Create a package named `patterns` in the `04-design-patterns` folder +2. Implement the design pattern in that package +3. Implement a corresponding unit test +4. Create an example application that uses the design pattern in the file `04-design-patterns/main.go` +5. Zip the source code and upload From 16aad9f5596eba258889486ade28ae921a828342 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 11:33:21 +0000 Subject: [PATCH 15/23] concurrency --- go/05-concurrency/deadlock.go | 17 +++++++ go/05-concurrency/mergeSort.go | 86 ++++++++++++++++++++++++++++++++++ go/05-concurrency/select.go | 19 ++++++++ 3 files changed, 122 insertions(+) create mode 100644 go/05-concurrency/deadlock.go create mode 100644 go/05-concurrency/mergeSort.go create mode 100644 go/05-concurrency/select.go diff --git a/go/05-concurrency/deadlock.go b/go/05-concurrency/deadlock.go new file mode 100644 index 0000000..931c201 --- /dev/null +++ b/go/05-concurrency/deadlock.go @@ -0,0 +1,17 @@ +package main + +func print(ci <-chan int) { + //TODO: implement +} + +func main() { + + c := make(chan int) + + c <- 1 + c <- 2 + c <- 3 + close(c) + + print(c) +} diff --git a/go/05-concurrency/mergeSort.go b/go/05-concurrency/mergeSort.go new file mode 100644 index 0000000..4160246 --- /dev/null +++ b/go/05-concurrency/mergeSort.go @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "math/rand" + "sort" + "time" +) + +func mergeSortSequential(data []float64) { + if len(data) <= 1 { + return + } + + mid := len(data) / 2 + left := data[:mid] + right := data[mid:] + + mergeSortSequential(left) + mergeSortSequential(right) + + copy(data, merge(left, right)) +} + +func merge(left, right []float64) []float64 { + result := make([]float64, 0, len(left)+len(right)) + i, j := 0, 0 + + for i < len(left) && j < len(right) { + if left[i] < right[j] { + result = append(result, left[i]) + i++ + } else { + result = append(result, right[j]) + j++ + } + } + + result = append(result, left[i:]...) + result = append(result, right[j:]...) + + return result +} + +func main() { + + //1. DATA CREATION + data := make([]float64, 1000*1000*20) + + for i := range data { + data[i] = rand.Float64() * 100 // Random floats between 0 and 100 + } + + expected := make([]float64, len(data)) + copy(expected, data) + sort.Float64s(expected) + + //2. SORTING + start := time.Now() + + mergeSortSequential(data) + + elapsed := time.Since(start) + fmt.Printf("MergeSort took %s\n", elapsed) + + //3. VERIFICATION + if sort.Float64sAreSorted(data) { + fmt.Println("Data is sorted correctly") + } else { + fmt.Println("Data is NOT sorted correctly") + } + + if len(data) != len(expected) { + fmt.Println("Data and expected slices have different lengths") + return + } + + for i := range data { + if data[i] != expected[i] { + fmt.Println("Data and expected slices do not match") + return + } + } + + fmt.Println("Data and expected slices match") +} diff --git a/go/05-concurrency/select.go b/go/05-concurrency/select.go new file mode 100644 index 0000000..8af6e52 --- /dev/null +++ b/go/05-concurrency/select.go @@ -0,0 +1,19 @@ +package main + +import ( + "math/rand" + "time" +) + +func main() { + + ch1 := make(chan string) + + go func() { + time.Sleep(time.Duration(rand.Intn(5)+1) * time.Second) + ch1 <- "Message from channel 1" + }() + + msg1 := <-ch1 + println("Received:", msg1) +} From 1f74e707807978fea956b7ce4f0f37ba4e0d8676 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 15:46:12 +0200 Subject: [PATCH 16/23] cleanup dockerfile --- go/.devcontainer/Dockerfile | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/go/.devcontainer/Dockerfile b/go/.devcontainer/Dockerfile index 206f58f..a1ca4b5 100644 --- a/go/.devcontainer/Dockerfile +++ b/go/.devcontainer/Dockerfile @@ -2,20 +2,8 @@ FROM golang:1.25 RUN apt-get update && apt-get install -y build-essential -#RUN go install github.com/go-delve/delve/cmd/dlv@latest -#RUN go install github.com/cweill/gotests/gotests@v1.6.0 -#RUN go install golang.org/x/tools/gopls@latest -#RUN go install golang.org/x/tools/cmd/goimports@latest -#RUN go install honnef.co/go/tools/cmd/staticcheck@latest - -# allow all users to add go packages in that container -#RUN mkdir -p /go/pkg && chmod -R a+rwx /go/pkg -#RUN chmod -R a+rwx /go/pkg/mod /go/pkg/sumdb -#RUN chmod -R a+rwx /go/pkg/mod/github.com - ARG USERNAME=developer ARG USER_UID=1000 ARG USER_GID=$USER_UID RUN groupadd --gid $USER_GID $USERNAME && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME USER $USERNAME - From cd98a5154e248ed6d3410f5e8582249af049b05b Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Fri, 3 Oct 2025 10:15:45 +0200 Subject: [PATCH 17/23] added go.mod in hello world --- go/00-hello-world/go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 go/00-hello-world/go.mod diff --git a/go/00-hello-world/go.mod b/go/00-hello-world/go.mod new file mode 100644 index 0000000..42919e7 --- /dev/null +++ b/go/00-hello-world/go.mod @@ -0,0 +1,3 @@ +module gitty.informatik.hs-mannheim.de/steger/pr3-ws202526/go/00-hello-world/hello-world + +go 1.25.0 From c4018d0d015647192178195cc154681efaf956d2 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Mon, 13 Oct 2025 12:36:59 +0200 Subject: [PATCH 18/23] documentation for methods and interfaces --- go/02-next-level/00-methods.go | 6 ++++-- go/02-next-level/01-interfaces.go | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/go/02-next-level/00-methods.go b/go/02-next-level/00-methods.go index a005976..ae1a6ac 100644 --- a/go/02-next-level/00-methods.go +++ b/go/02-next-level/00-methods.go @@ -6,12 +6,14 @@ type Counter struct { value int } -// pointer receiver +// pointer receiver. The method operates directly on the object c points to +// Use a pointer receiver whenever the object needs to be modified. func (c *Counter) Increment() { c.value++ } -// value receiver +// value receiver. The method operates on copy of object c. Use a value +// receiver when the object does not need to be modified in the method. func (c Counter) String() string { return fmt.Sprintf("Counter value: %d", c.value) } diff --git a/go/02-next-level/01-interfaces.go b/go/02-next-level/01-interfaces.go index 6a6e25f..c0eb97f 100644 --- a/go/02-next-level/01-interfaces.go +++ b/go/02-next-level/01-interfaces.go @@ -14,12 +14,14 @@ type rect struct { width, height float64 } +// Ensure that rect implements the geometry interface var _ geometry = rect{} type circle struct { radius float64 } +// Ensure that circle implements the geometry interface var _ geometry = circle{} func (r rect) area() float64 { @@ -36,12 +38,16 @@ func (c circle) perim() float64 { return 2 * math.Pi * c.radius } +//Metods demonstrates how to use an interface func measure(g geometry) { fmt.Println(g) fmt.Println(g.area()) fmt.Println(g.perim()) } + +//Method demonstrates casting an interface to a concrete type. +//Should be avoided in practice whenever possible. func detectCircle(g geometry) { if c, ok := g.(circle); ok { fmt.Println("circle with radius", c.radius) From 0fd016ebb3218708d6942468db6ea31682075109 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Mon, 13 Oct 2025 12:40:02 +0200 Subject: [PATCH 19/23] added documentation for struct embeddings --- go/02-next-level/02-struct-embedding.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go/02-next-level/02-struct-embedding.go b/go/02-next-level/02-struct-embedding.go index 72f46fd..e1311ab 100644 --- a/go/02-next-level/02-struct-embedding.go +++ b/go/02-next-level/02-struct-embedding.go @@ -11,12 +11,12 @@ func (p Person) Say() { } type Student struct { - Person + Person //struct Person is embedded Semester int } type Teacher struct { - Person + Person //struct Person is embedded Subject string } @@ -30,9 +30,9 @@ func main() { max.Say() - daniel.Say() + daniel.Say() //can be invoked directly on Student - sebastian.Say() + sebastian.Say() //can be invoked directly on Teacher max = sebastian.Person From 362bf8202bb89cca5a35d9352e0c68549bd96839 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Mon, 22 Dec 2025 10:40:08 +0000 Subject: [PATCH 20/23] comments for inventory --- go/01-basics/inventory.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/go/01-basics/inventory.go b/go/01-basics/inventory.go index 52694e2..79e4868 100644 --- a/go/01-basics/inventory.go +++ b/go/01-basics/inventory.go @@ -2,14 +2,17 @@ package main import "fmt" +// a new type named Category that can hold integer values type Category int +// The go equivalent of an enum that enumerates different named Categories const ( - Electronics Category = iota - Groceries - Clothes + Electronics Category = iota //0 + Groceries //1 + Clothes //2 ) +// implementation of the fmt.Stringer interface. In that way, Categories can be printed using the fmt.Print* functions func (c Category) String() string { switch c { case Electronics: @@ -32,7 +35,8 @@ type Product struct { } // Add a new product to the inventory -func addProduct(inventory *[]Product, name string, price float64, quantity int, category Category) { +func addProduct(inventory *[]Product, //pointer to the slice of of Products that shall be modified. In that way it can serve as in input/output parameter + name string, price float64, quantity int, category Category) { // Check if the product already exists in the inventory for _, product := range *inventory { if product.Name == name { @@ -51,7 +55,8 @@ func addProduct(inventory *[]Product, name string, price float64, quantity int, } // Remove a product from the inventory -func removeProduct(inventory *[]Product, name string) { +func removeProduct(inventory *[]Product, //pointer to the slice of of Products that shall be modified. In that way it can serve as in input/output parameter + name string) { for i, product := range *inventory { if product.Name == name { *inventory = append((*inventory)[:i], (*inventory)[i+1:]...) @@ -62,8 +67,9 @@ func removeProduct(inventory *[]Product, name string) { fmt.Println("Product not found.") } -// Update the quantity of a product -func updateQuantity(inventory *[]Product, name string, newQuantity int) { +// Update the quantity of a product. +func updateQuantity(inventory *[]Product, //pointer to the slice of of Products that shall be modified. In that way it can serve as in input/output parameter + name string, newQuantity int) { for i, product := range *inventory { if product.Name == name { (*inventory)[i].Quantity = newQuantity @@ -77,7 +83,7 @@ func updateQuantity(inventory *[]Product, name string, newQuantity int) { // Display the inventory func displayInventory(inventory []Product) { fmt.Println("Inventory:") - for _, product := range inventory { + for _, product := range inventory { //iterating over a range returns pairs of index and the content of a container (here: inventory). Since we don't care about the index, we use _ as a placeholder. fmt.Printf("%s - %s (Price: $%.2f, Quantity: %d)\n", product.Name, product.Category, product.Price, product.Quantity) } From 0c79676b86074d0c4943bed143322f4c834945a2 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Tue, 7 Apr 2026 12:46:13 +0000 Subject: [PATCH 21/23] added comments --- go/02-next-level/03-errors.go | 15 +++++++++++---- go/02-next-level/04-closure.go | 11 ++++++++--- go/02-next-level/05-generics.go | 21 +++++++++++++++++---- go/02-next-level/06-defer.go | 25 +++++++++++++++---------- 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/go/02-next-level/03-errors.go b/go/02-next-level/03-errors.go index 983549b..6e68e3b 100644 --- a/go/02-next-level/03-errors.go +++ b/go/02-next-level/03-errors.go @@ -5,23 +5,28 @@ import ( "fmt" ) +// a function that can fail, so it returns an error as the second return value func f(arg int) (int, error) { if arg == 42 { - - return -1, errors.New("can't work with 42") + // in case of an error, return the zero value for the result and a non-nil error + return 0, errors.New("can't work with 42") } + // simply return the result and a nil error in the success case return arg + 3, nil } +// define some errors to use in makeTea var ErrOutOfTea = fmt.Errorf("no more tea available") var ErrPower = fmt.Errorf("can't boil water") +// a function that can fail in multiple ways, so it returns an error as the second return value func makeTea(arg int) error { if arg == 2 { + // return the error directly, so we can check for it later with errors.Is return ErrOutOfTea } else if arg == 4 { - + // use %w to wrap the error, so we can check for it later with errors.Is return fmt.Errorf("making tea: %w", ErrPower) } return nil @@ -30,6 +35,7 @@ func makeTea(arg int) error { func main() { for _, i := range []int{7, 42} { + //typical pattern for checking errors in Go: if the error is not nil, handle it and return or continue; otherwise, use the result if r, e := f(i); e != nil { fmt.Println("f failed:", e) } else { @@ -40,9 +46,10 @@ func main() { for i := range 5 { if err := makeTea(i); err != nil { + // use errors.Is to check for specific errors, even if they are wrapped if errors.Is(err, ErrOutOfTea) { fmt.Println("We should buy new tea!") - } else if errors.Is(err, ErrPower) { + } else if errors.Is(err, ErrPower) { // this error is wrapped, but errors.Is can still check for it fmt.Println("Now it is dark.") } else { fmt.Printf("unknown error: %s\n", err) diff --git a/go/02-next-level/04-closure.go b/go/02-next-level/04-closure.go index f057a03..a7d0781 100644 --- a/go/02-next-level/04-closure.go +++ b/go/02-next-level/04-closure.go @@ -2,9 +2,11 @@ package main import "fmt" -func intSeq() func() int { - i := 0 - return func() int { +// a closure is a function value that references variables from outside its body. +// The function may access and assign to the referenced variables; in this sense the function is "bound" to the variables. +func intSeq() func() int { //returns a function that returns an int + i := 0 // i is a variable that intSeq's function value will reference. It continues to exist even after intSeq returns. + return func() int { // the anonomous function is returned here. It is not executed yet. i++ return i } @@ -12,12 +14,15 @@ func intSeq() func() int { func main() { + //functions are first class citizens in Go, so we can assign them to variables, + // pass them as arguments to other functions, and return them from functions. nextInt := intSeq() fmt.Println(nextInt()) fmt.Println(nextInt()) fmt.Println(nextInt()) + //a second function value from intSeq, with its own i variable. newInts := intSeq() fmt.Println(newInts()) } diff --git a/go/02-next-level/05-generics.go b/go/02-next-level/05-generics.go index 09fe044..ac9e9fe 100644 --- a/go/02-next-level/05-generics.go +++ b/go/02-next-level/05-generics.go @@ -2,6 +2,9 @@ package main import "fmt" +// a generic function that takes a slice of any type and a value of that type, and returns the index of the value in the slice, or -1 if it is not found. +// The type parameters S and E are declared in square brackets before the function name, and they can be used in the function signature and body. +// The constraint comparable means that the type E must support the == operator, which is necessary for comparing the value with the elements of the slice. func SlicesIndex[S []E, E comparable](s S, v E) int { for i := range s { if v == s[i] { @@ -11,15 +14,21 @@ func SlicesIndex[S []E, E comparable](s S, v E) int { return -1 } +// represents a linked list of any type T. The type parameter T is used in the definition of List and its methods, +// and it can be instantiated with any type when we create a List value. The type any is in fact defined as +// an empty interface. Thanks to duck-typing it can be used to represent any type, but it does not provide any +// operations on the values of that type. type List[T any] struct { head, tail *element[T] } +// the generic element of the linked list type element[T any] struct { next *element[T] val T } +// adds an instance of the generic type to the list func (lst *List[T]) Push(v T) { if lst.tail == nil { lst.head = &element[T]{val: v} @@ -30,7 +39,8 @@ func (lst *List[T]) Push(v T) { } } -func (lst *List[T]) AllElements() []T { +// returns all elements of the list as a slice of the generic type. +func (lst List[T]) AllElements() []T { var elems []T for e := lst.head; e != nil; e = e.next { elems = append(elems, e.val) @@ -39,14 +49,17 @@ func (lst *List[T]) AllElements() []T { } func main() { - var s = []string{"foo", "bar", "zoo"} - fmt.Println("index of zoo:", SlicesIndex(s, "zoo")) - _ = SlicesIndex[[]string, string](s, "zoo") + var s = []string{"foo", "bar", "zoo"} + // The types S and E are explicitly specified as []string and string respectively. + fmt.Println("index of zoo:", SlicesIndex[[]string, string](s, "zoo")) var s2 = []int{2, 4, 5, 6} + // The type E is inferred from the type of the value 4, which is int, + // and the type S is inferred from the type of the slice s2, which is []int. fmt.Println("index of 4: ", SlicesIndex(s2, 4)) + // instantiate a list of float64 elements lst := List[float64]{} lst.Push(10) lst.Push(13) diff --git a/go/02-next-level/06-defer.go b/go/02-next-level/06-defer.go index fde5ef5..e0af38a 100644 --- a/go/02-next-level/06-defer.go +++ b/go/02-next-level/06-defer.go @@ -7,18 +7,21 @@ import ( func main() { - f := createFile("/tmp/defer.txt") - defer closeFile(f) - writeFile(f) -} - -func createFile(p string) *os.File { fmt.Println("creating") - f, err := os.Create(p) + f, err := os.Create("/tmp/defer.txt") + + // defer the closing of the file until the surrounding function returns. + // This ensures that the file will be closed even if there is a panic or an early return in the function. + defer closeFile(f) + if err != nil { panic(err) } - return f + + //will not be called in case of a panic before + writeFile(f) + + // closeFile will be called here due to the defer-statement, even in case of a panic before. } func writeFile(f *os.File) { @@ -28,8 +31,10 @@ func writeFile(f *os.File) { func closeFile(f *os.File) { fmt.Println("closing") - err := f.Close() - + var err error + if f != nil { + err = f.Close() + } if err != nil { panic(err) } From eeb9217f9fa6a0cb3c679a071cfef133cbdc8576 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Tue, 7 Apr 2026 13:31:16 +0000 Subject: [PATCH 22/23] comments --- go/03-modules/main.go | 10 +++++++++- go/03-modules/myMath/math.go | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/go/03-modules/main.go b/go/03-modules/main.go index ab01282..923a1d4 100644 --- a/go/03-modules/main.go +++ b/go/03-modules/main.go @@ -3,9 +3,17 @@ package main import ( "fmt" + // importing the myMath package with an alias mm. This allows us to use mm instead of myMath to access the functions in the package. + // go packages are imported using their full path, which is the path to the package relative to the GOPATH or module root. . mm "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" - //_ "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + // the underscore is used to import a package solely for its side effects (i.e., the init function). + // This is useful when you want to initialize a package but do not need to access any of its exported functions or variables. + // _ "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + + // importing a third-party package from GitHub. This package provides functions for generating UUIDs (Universally Unique Identifiers). + // To use this package, you need to run go get github.com/google/uuid to download and install the package in your Go workspace. + // Alternatively, you can run go mod tidy to automatically download and install any missing dependencies based on the imports in your code. "github.com/google/uuid" //run go get github.com/google/uuid //or go mod tidy => go.sum diff --git a/go/03-modules/myMath/math.go b/go/03-modules/myMath/math.go index de9b318..f348cd8 100644 --- a/go/03-modules/myMath/math.go +++ b/go/03-modules/myMath/math.go @@ -2,14 +2,18 @@ package myMath import "fmt" +// init is a special function that is called automatically when the package is imported. It is used to initialize the package +// and can be used to set up any necessary state or perform any necessary setup before the package is used. func init() { fmt.Println("initializing myMath") } +// functions that start with an uppercase letter are exported and can be accessed from outside the package func Add(a, b int) int { return a + b } +// functions that start with a lowercase letter are not exported and cannot be accessed from outside the package func greater(a, b int) bool { return a > b } From 89659f766819c7bc05af1facdec171883e60705a Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Tue, 7 Apr 2026 13:46:19 +0000 Subject: [PATCH 23/23] update repo path --- go/03-modules/go.mod | 4 ++-- go/03-modules/main.go | 4 ++-- go/03-modules/myMath/math_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go/03-modules/go.mod b/go/03-modules/go.mod index e56e608..d5f08c0 100644 --- a/go/03-modules/go.mod +++ b/go/03-modules/go.mod @@ -1,5 +1,5 @@ -module gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules +module gitty.informatik.hs-mannheim.de/steger/pr3-sose2026/go/03-modules -go 1.25.0 +go 1.26.1 require github.com/google/uuid v1.6.0 diff --git a/go/03-modules/main.go b/go/03-modules/main.go index 923a1d4..d32a521 100644 --- a/go/03-modules/main.go +++ b/go/03-modules/main.go @@ -5,11 +5,11 @@ import ( // importing the myMath package with an alias mm. This allows us to use mm instead of myMath to access the functions in the package. // go packages are imported using their full path, which is the path to the package relative to the GOPATH or module root. . - mm "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + mm "gitty.informatik.hs-mannheim.de/steger/pr3-sose2026/go/03-modules/myMath" // the underscore is used to import a package solely for its side effects (i.e., the init function). // This is useful when you want to initialize a package but do not need to access any of its exported functions or variables. - // _ "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + // _ "gitty.informatik.hs-mannheim.de/steger/pr3-sose2026/go/03-modules/myMath" // importing a third-party package from GitHub. This package provides functions for generating UUIDs (Universally Unique Identifiers). // To use this package, you need to run go get github.com/google/uuid to download and install the package in your Go workspace. diff --git a/go/03-modules/myMath/math_test.go b/go/03-modules/myMath/math_test.go index cf3fe11..303d05e 100644 --- a/go/03-modules/myMath/math_test.go +++ b/go/03-modules/myMath/math_test.go @@ -3,7 +3,7 @@ package myMath_test import ( "testing" - "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/03-modules/myMath" + "gitty.informatik.hs-mannheim.de/steger/pr3-sose2026/go/03-modules/myMath" ) func TestAdd(t *testing.T) {