From 0317d26add58bcff114b4403e546e7637af43671 Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 21 Apr 2026 15:26:29 +0200 Subject: [PATCH 1/2] 06: Demos und Labor --- web/06/demos/helloworld/helloworld.go | 7 +++ web/06/demos/taskmanager/go.mod | 3 + web/06/demos/taskmanager/main.go | 82 +++++++++++++++++++++++++++ web/06/demos/taskmanager/task.go | 60 ++++++++++++++++++++ web/06/demos/taskmanager/tasks.json | 24 ++++++++ web/06/labor/06_aufgaben.md | 73 ++++++++++++++++++++++++ web/06/labor/workshop-anmeldung.html | 66 +++++++++++++++++++++ 7 files changed, 315 insertions(+) create mode 100644 web/06/demos/helloworld/helloworld.go create mode 100644 web/06/demos/taskmanager/go.mod create mode 100644 web/06/demos/taskmanager/main.go create mode 100644 web/06/demos/taskmanager/task.go create mode 100644 web/06/demos/taskmanager/tasks.json create mode 100644 web/06/labor/06_aufgaben.md create mode 100644 web/06/labor/workshop-anmeldung.html diff --git a/web/06/demos/helloworld/helloworld.go b/web/06/demos/helloworld/helloworld.go new file mode 100644 index 0000000..c048119 --- /dev/null +++ b/web/06/demos/helloworld/helloworld.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("hello world") +} diff --git a/web/06/demos/taskmanager/go.mod b/web/06/demos/taskmanager/go.mod new file mode 100644 index 0000000..f64ceb6 --- /dev/null +++ b/web/06/demos/taskmanager/go.mod @@ -0,0 +1,3 @@ +module example.com/taskmanager + +go 1.24.5 diff --git a/web/06/demos/taskmanager/main.go b/web/06/demos/taskmanager/main.go new file mode 100644 index 0000000..668daf3 --- /dev/null +++ b/web/06/demos/taskmanager/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // Frage: Was macht dieser Teil genau? + if len(os.Args) < 2 { + fmt.Println("Usage: add | list | done ") + return + } + + // Lädt alle Tasks aus JSON-Datei in eine Liste + // Gibt eine leere Liste zurück, falls die JSON-Datei noch nicht existiert + // Gibt Fehlermeldung vom Typ error zurück, falls etwas schief gelaufen ist + tasklist, err := LoadTasks("tasks.json") + + // TODO: Fehlerbehandlung + if err != nil { + fmt.Println("Fehler beim Laden der JSON-Datei: " + err.Error()) + } + + // Je nach Kommandozeilenargument wird: + // - Task neu erstellt und zur Liste hinzugefügt (auch in JSON-Datei) + // - Alle Tasks aus der Liste ausgegeben inkl. Status ("✓" für done, sonst " ") + // - Task als done markiert und Ergebnis ausgegeben + switch os.Args[1] { + case "add": + // TODO: Prüfen, ob 3. Kommandozeilenargument für Title vorliegt + if len(os.Args) < 3 { + fmt.Println("Geben Sie einen Titel ein.") + return + } + + // TODO: Task zur Liste hinzufügen + tasklist.Add(os.Args[2]) + + // TODO: Liste in JSON-Datei speichern + tasklist.Save("tasks.json") + + // Ergebnis ausgeben + fmt.Println("Task added.") + + case "list": + // TODO: Durch alle Tasks der Liste iterieren + for _, task := range tasklist.Tasks { + // TODO: Task-Status bestimmen und inklusive ID und Title ausgeben + status := " " + if task.Done { + status = "✓" + } + fmt.Printf("[%s] %d: %s\n", status, task.ID, task.Title) + + } + + case "done": + // TODO: Prüfen, ob 3. Kommandozeilenargument für ID vorliegen + if len(os.Args) < 3 { + fmt.Println("Geben Sie eine ID ein.") + return + } + + // TODO: Prüfen, ob ID vom Typ integer, sonst Fehlermeldung und Abbruch + // Tipp: strconv.Atoi(string) + id, err := strconv.Atoi(os.Args[2]) + if err != nil { + fmt.Println("Falsche Eingabe der ID") + return + } + // TODO: Task auf done setzen + tasklist.Complete(id) + + // TODO: Taskliste in JSON-Datei speichern + tasklist.Save("tasks.json") + + // Ergebnis ausgeben + fmt.Println("Task marked as done.") + } +} diff --git a/web/06/demos/taskmanager/task.go b/web/06/demos/taskmanager/task.go new file mode 100644 index 0000000..6816c96 --- /dev/null +++ b/web/06/demos/taskmanager/task.go @@ -0,0 +1,60 @@ +package main + +import ( + "encoding/json" + "os" +) + +// TODO: Task repräsentiert eine einzelne To-Do-Aufgabe mit ID, Titel und Status. +// Tipp: struct verwenden +type Task struct { + ID int `json:"id"` + Title string `json:"title"` + Done bool `json:"done"` +} + +// TODO: TaskList enthält eine Liste von Aufgaben (Tasks). +type TaskList struct { + Tasks []Task `json:"tasks"` +} + +// TODO: Fügt einen neuen Task mit übergebenen Titel in die Liste ein. +// Die neue ID entspricht der Anzahl der Elemente in der Liste. (ok, weil keine Tasks gelöscht werden) +func (tl *TaskList) Add(title string) { + id := len(tl.Tasks) + 1 + newTask := Task{ID: id, Title: title, Done: false} + tl.Tasks = append(tl.Tasks, newTask) +} + +// TODO: Setzt vorhandenen Task mit übergebener ID auf den Status done. +// Annahme: Wir wissen nicht, wie ID erstellt wird. +func (tl *TaskList) Complete(id int) { + for i := range tl.Tasks { + if tl.Tasks[i].ID == id { + tl.Tasks[i].Done = true + } + } +} + +// Liste wird im JSON-Format in einer Datei mit übergebenen Dateinamen gespeichert +func (tl *TaskList) Save(filename string) error { + data, err := json.MarshalIndent(tl, "", " ") + if err != nil { + return err + } + return os.WriteFile(filename, data, 0644) +} + +// TODO: Lädt eine Liste von Tasks aus einer JSON-Datei (Dateiname als Parameter übergeben) +// Falls die Datei noch nicht existiert, wird eine leere Liste (neu) zurückgegeben +// Tipp 1: Einlesen einer Datei: os.ReadFile(filename) +// Tipp 2: JSON-Daten in TaskList-Struktur umwandeln: json.Unmarshal(data, &tl) +func LoadTasks(filename string) (*TaskList, error) { + data, err := os.ReadFile(filename) + if err != nil { + return &TaskList{}, nil + } + var tl TaskList + jsonErr := json.Unmarshal(data, &tl) + return &tl, jsonErr +} diff --git a/web/06/demos/taskmanager/tasks.json b/web/06/demos/taskmanager/tasks.json new file mode 100644 index 0000000..dcbb27f --- /dev/null +++ b/web/06/demos/taskmanager/tasks.json @@ -0,0 +1,24 @@ +{ + "tasks": [ + { + "id": 1, + "title": "Vorlesung besuchen", + "done": true + }, + { + "id": 2, + "title": "Go by Example durcharbeiten", + "done": true + }, + { + "id": 3, + "title": "Webserver lokal installieren", + "done": false + }, + { + "id": 4, + "title": "Uebungen durcharbeiten", + "done": false + } + ] +} \ No newline at end of file diff --git a/web/06/labor/06_aufgaben.md b/web/06/labor/06_aufgaben.md new file mode 100644 index 0000000..c007bd7 --- /dev/null +++ b/web/06/labor/06_aufgaben.md @@ -0,0 +1,73 @@ +# Übungsblatt 06 + +## 1. SWAGGER-Übung: Workshop-API + +**Aufgabenstellung**: Erstellen Sie eine OpenAPI-Spezifikation für die Workshop-Anmeldung aus Übungsblatt 04 ([HTML-Formular](workshop-anmeldung.html)). + +#### Arbeitsschritte + +1. Setzen die OpenAPI-Version auf `3.0.0`. +2. Setzen Sie Meta-Daten wie Titel und API-Version im Info-Objekt. +3. Setzen Sie `https://web4-637691723779.europe-west1.run.app` als URL im Servers-Objekt. +4. Setzen Sie einen **Pfad** `/registrierung` für die HTTP-Methode `POST`. Definieren Sie eine Beschreibung, den Request-Body sowie mögliche Antworten des Servers. + 1. Request-Body für die Übergabe von **Formulardaten** + 2. Request-Body für die Übergabe von **JSON-Daten** + + _Tipp: Verwenden Sie das Components-Objekt._ + +5. Verwenden Sie Enums (https://swagger.io/docs/specification/v3_0/data-models/enums/) für die Spezifikation der Checkboxen und der Radiobuttons (s. Hinweis unten). + - Beispiel für `enum` in JSON-OpenAPI: + ```json + "farbe": { + "type": "string", + "enum": ["rot","gruen","blau"], + "example": "gruen" + }, + ``` +6. Testen Sie Ihre API-Spezifikation mit Swagger. + +#### Hinweis +Der serverseitige API-Endpunkt hat sich geändert (neue URL: `https://web4-637691723779.europe-west1.run.app`) und wurde nun folgendermaßen implementiert: + +1. Wenn die Checkbox aktiviert wurde, wird für **agb**, **newsletter** und **equipment** nur noch der Wert (`value`-Attribut) _ja_ akzeptiert. +2. Für **format** werden die Werte (`value`-Attribut) _online_ und _praesenz_ akzeptiert, je nach dem, welcher Radiobutton aktiviert wurde. +3. Die Eingabefelder zu Vorname, Nachname, AGB und Format sind nun Pflichtfelder. + +## 2. Go-Übung: Kommandozeilenprogramm + +**Aufgabenstellung**: Entwickeln Sie ein Kommandozeilenprogramm in Go, mit dem Nutzer:innen ihre persönliche Büchersammlung verwalten können. + +#### Arbeitsschritte + +Implementieren Sie ein Programm mit folgenden Funktionen: + +1. **Buch hinzufügen** + ```bash + go run main.go book.go add "Titel" "Autor" + ``` + → Fügt ein neues Buch zur Sammlung hinzu. + +2. **Bücher auflisten** + ```bash + go run main.go book.go list + ``` + → Zeigt alle Bücher mit ID, Titel, Autor und Lesestatus. + +3. **Buch als gelesen markieren** + ```bash + go run main.go book.go read + ``` + → Markiert das Buch mit der angegebenen ID als gelesen. + +4. **Persistenz** + - Die Bücher sollen in einer Datei `books.json` gespeichert und beim Programmstart wieder geladen werden. + - Verwenden Sie dafür das `encoding/json`-Paket und `os.ReadFile` / `os.WriteFile`. + +### Hinweise + +- Verwenden Sie `struct` für die Buch- und Bibliotheksdaten. +- Arbeiten Sie mit `slice` zur Verwaltung der Bücherliste. +- Nutzen Sie Methoden zur Kapselung von Logik (z. B. `Add`, `MarkRead`, `Save`). +- Behandeln Sie Fehler sinnvoll und benutzerfreundlich. +- Strukturieren Sie Ihr Projekt in mindestens zwei Dateien (`main.go`, `book.go`). + diff --git a/web/06/labor/workshop-anmeldung.html b/web/06/labor/workshop-anmeldung.html new file mode 100644 index 0000000..72403ff --- /dev/null +++ b/web/06/labor/workshop-anmeldung.html @@ -0,0 +1,66 @@ + + + + + + Workshop-Anmeldung + + + +
+
+ Persönliche Angaben: +
+
+ +
+
+ +
+
+ +
+

+
+ +
+ Kursauswahl: +
+

+ +
+
+
+ +
+ Zusätzliche Optionen: + +
+ + +
+ + +
+
+ +
+ Teilnahmeformat: + Format wählen:
+ +
+ + +
+
+
+ +
+ + + \ No newline at end of file From 277cd1554128c475c484f4dd6923302cb87e6f3a Mon Sep 17 00:00:00 2001 From: Teena Steger Date: Tue, 21 Apr 2026 15:29:56 +0200 Subject: [PATCH 2/2] 06: Anleitung zu go modules --- web/06/labor/06_aufgaben.md | 2 +- web/06/labor/anleitung_extlib.md | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 web/06/labor/anleitung_extlib.md diff --git a/web/06/labor/06_aufgaben.md b/web/06/labor/06_aufgaben.md index c007bd7..dd6a465 100644 --- a/web/06/labor/06_aufgaben.md +++ b/web/06/labor/06_aufgaben.md @@ -69,5 +69,5 @@ Implementieren Sie ein Programm mit folgenden Funktionen: - Arbeiten Sie mit `slice` zur Verwaltung der Bücherliste. - Nutzen Sie Methoden zur Kapselung von Logik (z. B. `Add`, `MarkRead`, `Save`). - Behandeln Sie Fehler sinnvoll und benutzerfreundlich. -- Strukturieren Sie Ihr Projekt in mindestens zwei Dateien (`main.go`, `book.go`). +- Strukturieren Sie Ihr Projekt in mindestens zwei Dateien (`main.go`, `book.go`). Hierzu müssen Sie Module verwenden. Eine kurze Anleitung dazu finden Sie hier: [Abhängigkeiten mit go.mod](anleitung_extlib.md) diff --git a/web/06/labor/anleitung_extlib.md b/web/06/labor/anleitung_extlib.md new file mode 100644 index 0000000..066e4ea --- /dev/null +++ b/web/06/labor/anleitung_extlib.md @@ -0,0 +1,26 @@ +# Abhängigkeitsverwaltung mit `go.mod` + +## Hintergrund + +Externe Pakete, die im Code importiert werden, werden über eine `go.mod`‑Datei verwaltet. Diese Datei definiert das Modul und listet alle Abhängigkeiten auf. Sie gehört fest zum Projekt und wird im Quellcode‑Repository mitgeführt. + +## Anweisungen + +*Annahme*: Go-Programm ist bereits vorhanden und die Imports im Code sind gesetzt. Außerdem befinden Sie sich in dem Ordner mit dem Go-Programm. + +1. **Modul initialisieren (falls noch nicht geschehen)** +```bash +go mod init example.com/myapp +``` +Der Modulpfad entspricht in der Praxis meist der Repository‑Adresse, z. B. `github.com/mymodule`. Für einfache Beispiele genügt ein Platzhalter wie z.B. `example.com/myapp` + +2. **Abhängigkeiten auflösen und aufräumen** +```bash +go mod tidy +``` +Dadurch werden alle im Code verwendeten Imports heruntergeladen und ins `go.mod` eingetragen. Nicht mehr benötigte Pakete werden entfernt. + +3. **Programm starten** +```bash +go run . +``` \ No newline at end of file