1
0
Fork 0

Merge remote-tracking branch 'upstream/main'

# Conflicts:
#	go/01-basics/calculator.go
#	go/01-basics/inventory.go
#	go/02-next-level/02-struct-embedding.go
ChaosLL1337 2026-10-21 06:52:31 +00:00
commit e17734dab4
8 changed files with 211 additions and 106 deletions

View File

@ -1,3 +1,3 @@
module gitty.informatik.th-mannheim.de/steger/pr3-sose2026/go/00-hello-world/hello-world
module gitty.informatik.th-mannheim.de/steger/pr3-ws202526/go/00-hello-world/hello-world
go 1.26.0

View File

@ -13,33 +13,23 @@ func main() {
exit = "exit"
)
//TODO: implement according to README.md
fmt.Println("Welcome to the Simple Calculator!")
for {
var operation string
fmt.Print("\nEnter operation (add, subtract, multiply, divide, exit): ")
fmt.Scan(&operation)
//the following code just demonstrates how to use fmt.Scan
if operation == exit {
fmt.Println("Goodbye!")
break
}
var str string
fmt.Print("Please enter a string: ")
fmt.Scan(&str)
var num1, num2 float64
fmt.Print("Enter the first number: ")
fmt.Scan(&num1)
fmt.Print("Enter the second number: ")
fmt.Scan(&num2)
var x float64
fmt.Print("Please enter a float: ")
fmt.Scan(&x)
fmt.Printf("You entered '%s' and %f\n", str, x)
switch operation {
case add:
fmt.Printf("Result: %.2f\n", num1+num2)

View File

@ -1,15 +1,20 @@
package main
package main
import "fmt"
type Category int
const (
Electronics Category = iota
Groceries
Clothes
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 //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:
@ -23,99 +28,93 @@ func (c Category) String() string {
}
}
// 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)
// implementation of the fmt.Stringer interface for printing products
func (p Product) String() string {
return fmt.Sprintf("%s (%s, Price: $%.2f, Quantity: %d)", p.Name, p.Category, p.Price, p.Quantity)
}
// 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
}
func addProduct(inventory map[string]Product, name string, price float64, quantity int, category Category) {
//do not create a new product in case a product with the name already exists
if _, exists := inventory[name]; exists {
fmt.Printf("Unable to add new Product %s: Product already exists.\n", name)
return
}
fmt.Println("Product not found.")
//create a new product...
p := Product{name, price, quantity, category}
inventory[name] = p // ...and insert it into the map
}
// 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.")
func removeProduct(inventory map[string]Product, name string) {
//no checks required. Does nothing if the product doesn't exist.
delete(inventory, name)
}
// 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 updateQuantity(inventory map[string]Product, name string, newQuantity int) {
p := inventory[name] //read from the map
p.Quantity = newQuantity //update value
inventory[name] = p //store back into the map
}
func displayInventory(inventory map[string]Product) {
//Iterate over the inventory
i := 1
for _, p := range inventory { //don't care about the key (_), only the value (p) is relevant
fmt.Printf("%d. %s\n", i, p)
i++
}
}
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},
fmt.Println("Welcome to the Inventory Manager!")
// Store a fixed list of initial product names in an array.
initialProductNames := [...]string{"Laptop"}
// Convert the array into a slice so the inventory can grow or shrink dynamically.
productNames := initialProductNames[:]
productNames = append(productNames, "Apples", "T-shirt")
// Use a map to associate product names with details like quantity, price, and category.
prices := []float64{1000.0, 2.0, 10.0}
quantities := []int{5, 50, 20}
categories := []Category{Electronics, Groceries, Clothes}
inventory := make(map[string]Product)
for i, name := range productNames {
inventory[name] = Product{name, prices[i], quantities[i], categories[i]}
}
// Display initial inventory
fmt.Println("\nInitial Inventory:")
displayInventory(inventory)
// Add a new product
addProduct(&inventory, "Phone", 800, 10, "Electronics")
addProduct(&inventory, "Phone", 800, 10, Electronics)
fmt.Println("\nAdding a new product: Phone (Electronics, Price: $800, Quantity: 10)")
addProduct(inventory, "Phone", 800, 10, Electronics)
// Display updated inventory
fmt.Println("\nUpdated Inventory:")
displayInventory(inventory)
// Update the quantity of an existing product
updateQuantity(&inventory, "Apples", 30)
fmt.Println("\nUpdating quantity for Apples: New Quantity = 30")
updateQuantity(inventory, "Apples", 30)
// Remove a product
removeProduct(&inventory, "T-shirt")
fmt.Println("\nRemoving product: T-shirt")
removeProduct(inventory, "T-shirt")
// Display final inventory
fmt.Println("\nFinal Inventory:")
displayInventory(inventory)
}
}

View File

@ -0,0 +1,26 @@
package main
import "fmt"
type Counter struct {
value int
}
// 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. 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)
}
func main() {
c := Counter{}
fmt.Println(c)
c.Increment()
fmt.Println(c)
}

View File

@ -0,0 +1,66 @@
package main
import (
"fmt"
"math"
)
type geometry interface {
area() float64
perim() float64
}
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 {
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
}
//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)
}
}
func main() {
r := rect{width: 3, height: 4}
c := circle{radius: 5}
measure(r)
measure(c)
detectCircle(r)
detectCircle(c)
}

View File

@ -11,12 +11,12 @@ func (p Person) Say() {
}
type Student struct {
Person //struct Person is embedded
Person //struct Person is embedded
Semester int
}
type Teacher struct {
Person //struct Person is embedded
Person //struct Person is embedded
Subject string
}

View File

@ -2,7 +2,10 @@ package main
import "fmt"
func SlicesIndex[S []E, E int](s []string, v string) int {
// 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] {
return i
@ -11,27 +14,34 @@ func SlicesIndex[S []E, E int](s []string, v string) int {
return -1
}
type List struct {
head, tail *element
// 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]
}
type element struct {
next *element
val int
// the generic element of the linked list
type element[T any] struct {
next *element[T]
val T
}
func (lst *List) Push(v int) {
// adds an instance of the generic type to the list
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
// 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,13 +49,21 @@ func (lst *List) AllElements() []int {
}
func main() {
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"))
fmt.Println("index of zoo:", SlicesIndex(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))
lst := List{}
// instantiate a list of float64 elements
lst := List[float64]{}
lst.Push(10)
lst.Push(13)
lst.Push(23)
lst.Push(23.3)
fmt.Println("list:", lst.AllElements())
}

View File

@ -6,18 +6,22 @@ import (
)
func main() {
f := createFile("/tmp/defer.txt")
writeFile(f)
closeFile(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) {
@ -27,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)
}