Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
Go lernen
go1.22.2 / Ubuntu 24.04.3 LTS
Einleitung
- Installation
> apt install golang-go > go version go version go1.22.2 linux/amd64
- Hallo Welt
> vim hello_gopher.go package main import ( "fmt" ) func main() { fmt.Println("Hallo Gopher!") } > go build hello_gopher.go > ./hello_gopher Hallo Gopher!
Das Erste Go-Projekt
- Erstes Go-Projekt
> vim main.go package main import ( "fmt" ) func main() { fmt.Println("Hallo Go-Projekt!") } > go build main.go > ./main Hallo Go-Projekt!
- Hilfe
> go help build | less
- Kode formatieren
> go fmt main.go
- Dokumentation
> go doc fmt.Println package fmt // import "fmt" func Println(a ...any) (n int, err error) Println formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error
Die Datentypen in Go
- Einfache Datentypen
- String, für Zeichenketten
stringin UTF-8-Kodierung
- Boolean, für boolesche Wahrheitswerte
bool: true oder false
- Zahlen, für von Integer bis Gleitkomma
int32int64float32float64
- komplexe Zahlen…
- Zusammengesetzte Datentypen
Array, Sequenz mehrerer Elemente mit fixer LängeSlice, Sequenz mehrerer Elemente mit variabler LängeMap, Wörterbuch, das Schlüssel auf einen Wert abbildet
Variablen und Konstanten
- Variablen
... func main() { // Deklaration und Zuweisung in langer Form var s1 string = "eine Zeichenkette" var i1 int = 123 var b1 bool = true fmt.Println(s1, i1, b1) }
- Package-Variable
... // Diese Variable ist im ganzen Package verwendbar var aPackageVar string = "eine globale Variable" func main() { fmt.Println("Hallo Go-Projekt!") }
- Konstanten
package main import ( "fmt" ) // Diese Konstante ist im ganzen Package verwendbar const aPackageKons = "eine globale Konstante" func main() { const k1 = "eine Zeichenkette" const k2 = 123 fmt.Println(k1, k2, k2+k2) fmt.Println(aPackageKons) }
Arrays und Slices
Arrays und Slices sind Sequenzen mehrerer Elemente.
Arrays haben eine feste Länge.
Slices haben eine variable Länge, es entspricht einer "Liste" in C++ oder Java.
- Array
package main import ( "fmt" ) func main() { // Array (mit 2 Elementen) initialisieren und füllen array01 := [2]string{"Element1", "Element2"} fmt.Println("unverändert", array01) // ein Element im Array ändern, das erste Element hat den Index "0" array01[1] = "Fritz" fmt.Println("verändert", array01) }
- Slice
package main import ( "fmt" ) func main() { // Slice mit make initialisieren slice01 := make ([]string, 2) slice01[0] = "Anita" slice01[1] = "Rom" fmt.Println(slice01) // Slice mit Werten initialisieren slice02 := []string{"Otto", "Hamburg"} fmt.Println(slice02) // Slice erweitern slice02 = append(slice02, "Bär", "Berlin") fmt.Println(slice02) }
Maps für Schlüssel/Werte-Paare
- Map
package main import ( "fmt" ) func main() { // Map mit make initialisieren var map01 = make (map[string]int) map01["Anita"] = 23 map01["Berta"] = 32 fmt.Println(map01) // Map mit Werten initialisieren var map02 = map[string]int{"Papa": 54, "Mama": 45} fmt.Println(map02) // Wert zu einem Schlüssel abrufen fmt.Println("Alter von Papa:", map02["Papa"]) }
Structs mit Feldern nutzen und definieren
In Go können mehrere Werte zu Strukturen ("Structs") zusammengefasst werden.
Mit Structs können Sie Daten kapseln, und das ganz ohne Objektorientierung.
Ein Struct ist ein einfacher Datenkontainer mit Feldern.
- Struct
package main import ( "fmt" ) type Struktur01 struct { Name string // mit großem Anfangsbuchstaben ist es ein öffentliches Feld alter int // mit kleinem Anfangsbuchstaben ist es ein privates Feld } // Struct einbinden type Struktur02 struct { Struktur01 // das Struct "Struktur02" hat nun alle Felder, die das Struct "Struktur01" hat und es können zusätzliche hinzugefügt werden passwort string } func main() { // normales Struct c := Struktur01{Name: "Alfred Nobel", alter: 63} fmt.Println(c) // ein Struct in ein anderes Struct einbinden d := Struktur02{passwort: "geheim"} d.Name = "Drachentöter" fmt.Println(d) // leeres Struct; es werden die initialen Werte ("0" und "leer") der Felder in Struktur01 ausgegeben var leereStruktur Struktur01 fmt.Println(leereStruktur) }
Pointer
- pointer.go
package main import ( "fmt" ) type Struktur01 struct { Name string // mit großem Anfangsbuchstaben ist es ein öffentliches Feld alter int // mit kleinem Anfangsbuchstaben ist es ein privates Feld } func main() { // normales Struct c := Struktur01{Name: "Alfred Nobel", alter: 63} // Pointer p auf Struct c var p *Struktur01 = &c // Pointer mit * auflösen und Wert zuweisen (Überschreiben) (*p).Name = "Gorilla" fmt.Println("c:", c) fmt.Println("Pointer auf c:", p) }
Der leere Wert nil
- nil.go
package main import ( "fmt" ) type Struktur01 struct { Name string // mit großem Anfangsbuchstaben ist es ein öffentliches Feld alter int // mit kleinem Anfangsbuchstaben ist es ein privates Feld } func main() { // Pointer ist nil var p *Struktur01 // prüfen ob der Pointer p nil ist fmt.Println("Pointer p ist nil:", p == nil) // Slice ist nil var s []float64 fmt.Println("Slice s ist nil:", s == nil) // Map ist nil var m map[string]float64 fmt.Println("Map m ist nil:", m == nil) }
Fehler
In Go gibt es keine Spezialbehandlung für Fehler. In Go sind Fehler Werte wie Strings, Integer oder Struts.
- Fehler.go
package main import ( "fmt" ) func main() { // Error err := fmt.Errorf("Benutzer %v wurde nicht gefunden", "Spenzer") fmt.Println("Error err:", err) }
In Go gibt es für Fehler den Typ "error". "error" ist ein gewöhnlicher Go-Datentyp, jedoch mit besonderer Bedeutung.
Den Kontrollfluss strukturieren
Kontrollstruktur if/else
- kontrolle_if.go
package main import ( "fmt" ) func main() { // if zweifler := "gehen" if zweifler != "laufen" { fmt.Println("Du sollst jetzt nicht laufen.") } // if/else geschwindigkeit := 100 if geschwindigkeit < 120 { fmt.Println("Du bist zu langsam.") } else if geschwindigkeit == 120 { fmt.Println("Die Geschwindigkeit stimmt.") } else { fmt.Println("Du bist zu schnell.") } }
Kontrollstruktur Switch
- kontrolle_switch.go
package main import ( "fmt" "time" ) func main() { // Switch mit Ausdruck geschwindigkeit := 100 switch { case geschwindigkeit < 120: fmt.Println("Du bist zu langsam.") case geschwindigkeit == 120: fmt.Println("Die Geschwindigkeit stimmt.") default: fmt.Println("Du bist zu schnell.") } // Switch über Typ switch time.Now().Weekday() { case time.Saturday: fmt.Println("Es ist Sonnabend.") case time.Sunday: fmt.Println("Es ist Sonntag.") default: fmt.Println("Es ist ein Arbeitstag.") } }
for-Schleife
- kontrolle_for.go
package main import ( "fmt" ) func main() { // klassische for-Schleife for i := 1; i < 7; i++ { fmt.Println("Durchlauf (for)", i) } // while-Schleife j := 1 for j < 7 { fmt.Println("Durchlauf (while)", j) j++ } // Endlos-Schleife //k := 1 //for { // fmt.Println("Durchlauf (while)", k) // k++ //} // for-each-Schleife mit range slice := []string{"Otto", "Didi", "Heinz"} for index, character := range slice { fmt.Println(index, "Character", character) } }
Übung
- kontrolle_uebung.go
package main import ( "fmt" ) func main() { // Übung: Alter vom Hund in Menschenjahren und Hundejahren for dogAge := 1; dogAge < 11; dogAge++ { HumanAge := dogAge * 7 fmt.Printf("Dog: %d, Human %d\n", dogAge, HumanAge) } }
Funktionen und Methoden
einfache Funktionen
- einfache_Funktionen.go
package main import ( "fmt" ) func humanAge1(dogAge int) int { return dogAge * 7 } func humanAge2(dogAge int) (humanAge int) { humanAge = dogAge * 7 return } func main() { // Übung: Alter vom Hund in Menschenjahren und Hundejahren hassoAge := 3 fmt.Println("1. Menschenalter von Hasso", humanAge1(hassoAge)) fmt.Println("2. Menschenalter von Hasso", humanAge2(hassoAge)) }
Funktionen mit mehreren Parametern und Rückgaben
- Funktionen_mit_mehreren_Parametern.go
package main import ( "fmt" ) func humanAge(dogAge int) int { return dogAge * 7 } func humanAges(dog1, dog2 int) (int, int) { return humanAge(dog1), humanAge(dog2) } func main() { human1, human2 := humanAges(3, 5) fmt.Println("Human Ages:", human1, ",", human2) }
Methoden an Strukturen definieren
- Struct_mit_Methode.go
package main import ( "fmt" ) // Struct type Struktur01 struct { Name string // mit großem Anfangsbuchstaben ist es ein öffentliches Feld alter int // mit kleinem Anfangsbuchstaben ist es ein privates Feld } // Methode func (c Struktur01) methode01() { fmt.Println("Ausgabe der Methode:", c.Name) } func main() { // normales Struct c := Struktur01{Name: "Alfred Nobel", alter: 63} // Aufruf Methode an Struct c.methode01() fmt.Println(c) }
Mit Fehlern in Funktionen umgehen
- Fehler_in_Funktionen.go
package main import ( "fmt" ) // Struktur type Congressman struct { Name string AccountBalance float64 } // Fehler als Rückgabewert // Der Kontostand eines bestechlichen Abgeordneten wird von dieser Methode erhöht // ist ein Abgeordneter nicht bestechlich, wird ein Fehler ausgegeben func (c Congressman) bestechung(amount float64) error { // ist der Name des Abgeordneten nicht Peter, so ist er nicht bestechlich if c.Name != "Peter" { return fmt.Errorf("%v ist nicht koruppt", c.Name) } c.AccountBalance += amount fmt.Println(c.Name, "hat", c.AccountBalance) return nil } func main() { //c := Congressman{Name: "Jacjie", AccountBalance: 8000.0} c := Congressman{Name: "Peter", AccountBalance: 8000.0} // Fehler behandeln err := c.bestechung(5000.0) if err != nil { fmt.Println("Ein Abgeordneter konnte nicht bestochen werden:", err) } fmt.Println(c) }
generische Funktionen
- generische_Funktionen.go
package main import ( "log" ) // generische Funktion func humanAge[T int | float64](dogAge T) T { return dogAge * 7 } func main() { // Funktion mit Typ Integer aufrufen var i int = humanAge(3) log.Println(i) // Funktion mit Typ Fließkomma aufrufen var j float64 = humanAge[float64](4.9) log.Println(j) }
anonyme Funktionen
- anonyme_Funktionen.go
package main import ( "fmt" "net/http" ) func main() { // anonyme Funktion definieren und ausführen func () { fmt.Println("Hallo Welt") }() // anonyme HTTP-Handler-Funktion http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hallo Welt")) }) http.ListenAndServe(":8080") }
verzögerte Ausführung
- verzögerte_Ausführung.go
package main import ( "fmt" ) // mit defer kann eine Ausführung verzögert werden func halloDefer() { defer fmt.Print("Welt\n") // defer wird auch bei einem Fehler ausgeführt // hier greifen wir in einem Slice auf eine Stelle (Index) zu, // die nicht existiert -> Fehler //var s = []string{} //fmt.Println("Huch ", s[42]) fmt.Print("Hallo ") } func main() { // verzögerte Ausführung mit defer halloDefer() }
Typische Anwendungsfälle für defer sind "Dateien schließen", "Dateien löschen" oder "Speicher freigeben".
