SlideShare a Scribd company logo
1 of 60
Download to read offline
Go in derPraxis
gh Github CLI
149.298 Zeilen Code
490 Contributors
1. 🖥️ CLI Tools
2. 🌐 Web App
3. λ Lambda Function
5 Fakten zu Go
1. statisches Typsystem
2. Garbage Collection
3. keine Vererbung
4. Concurrency eingebaut
5. native Ausführung
Linux, Win, z/OS, 386, amd64, ARM, wasm, ...
🖥️CLI Tool
Go Proverbs
Go Proverbs
18 Prinzipien zurGo Entwicklung
#
von Rob Pike 2015 vorgestellt
#
"Clearis betterthan clever."
#
CLI Proverbs ohne Argumente
> pro
Clear is better than clever.
CLI Projekt aufsetzen
// 1. Go Modul erstellen (erzeugt go.mod)
> go mod init crossnative.com/pro
// 2. Datei main.go erstellen
package main
import "fmt"
func main() {
fmt.Println("Hello Go Pro!")
}
Ausführen
go build . // 1. Code kompilieren
./pro // 2. Binary ausführen
go run . // Code kompilieren und ausführen
Entwicklung
JetBrains
GoLand
Visual
Studio Code Vim Go
Proverbs als Go Modul
Proverbs Modul nutzen
// 1. Proverbs Modul Dependency
> go get github.com/jboursiquot/go-proverbs
// 2. Go Modul Descriptor go.mod
module crossnative.com/pro
go 1.22
require github.com/jboursiquot/go-proverbs v0.0.2
Zufälliges Proverb ausgeben
import (
"github.com/jboursiquot/go-proverbs"
)
package main
1
2
3
"fmt"
4
5
6
7
func main() {
8
fmt.Println(proverbs.Random())
9
}
10
import (
"github.com/jboursiquot/go-proverbs"
)
fmt.Println(proverbs.Random())
package main
1
2
3
"fmt"
4
5
6
7
func main() {
8
9
}
10
package main
import (
"fmt"
"github.com/jboursiquot/go-proverbs"
)
func main() {
fmt.Println(proverbs.Random())
}
1
2
3
4
5
6
7
8
9
10
// Ausgabe `go run .`
&{Make the zero value useful. http://youtube.com/322}
💡Structs und Pointer
// Pointer Variable auf Proverb Struct
var p *proverbs.Proverb = proverbs.Random()
package main
1
2
import (
3
"fmt"
4
"github.com/jboursiquot/go-proverbs"
5
)
6
7
func main() {
8
9
10
11
fmt.Println(p)
12
}
13
package main
import (
"fmt"
"github.com/jboursiquot/go-proverbs"
)
func main() {
// Pointer Variable auf Proverb Struct
var p *proverbs.Proverb = proverbs.Random()
fmt.Println(p)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// Struct statt Klasse
type Proverb struct {
Saying string
Link string
}
1
2
3
4
5
Zufälliges Proverb ausgeben
import (
"github.com/jboursiquot/go-proverbs"
)
package main
1
2
3
"fmt"
4
5
6
7
func main() {
8
var p *proverbs.Proverb = proverbs.Random()
9
10
// Zugriff auf Property des Structs
11
fmt.Println(p.Saying)
12
}
13
import (
"github.com/jboursiquot/go-proverbs"
)
var p *proverbs.Proverb = proverbs.Random()
package main
1
2
3
"fmt"
4
5
6
7
func main() {
8
9
10
// Zugriff auf Property des Structs
11
fmt.Println(p.Saying)
12
}
13
// Zugriff auf Property des Structs
fmt.Println(p.Saying)
package main
1
2
import (
3
"fmt"
4
"github.com/jboursiquot/go-proverbs"
5
)
6
7
func main() {
8
var p *proverbs.Proverb = proverbs.Random()
9
10
11
12
}
13
package main
import (
"fmt"
"github.com/jboursiquot/go-proverbs"
)
func main() {
var p *proverbs.Proverb = proverbs.Random()
// Zugriff auf Property des Structs
fmt.Println(p.Saying)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// Ausgabe `go run .`
Make the zero value useful.
CLI Proverbs mit Count
> pro -count=3
Clear is better than clever.
Documentation is for users.
Don't panic.
Flag fürCount
"flag"
// 1. Flags definieren
var count *int = flag.Int("count", 1, "proverb count")
import (
1
2
"fmt"
3
"github.com/jboursiquot/go-proverbs"
4
)
5
6
func main() {
7
8
9
10
// 2. Flags parsen
11
flag.Parse()
12
13
// 3. Ausgabe in Schleife
14
for i := 0; i < *count; i++ {
15
var p *proverbs.Proverb = proverbs.Random()
16
fmt.Println(p.Saying)
17
}
18
}
19
// 2. Flags parsen
flag.Parse()
import (
1
"flag"
2
"fmt"
3
"github.com/jboursiquot/go-proverbs"
4
)
5
6
func main() {
7
// 1. Flags definieren
8
var count *int = flag.Int("count", 1, "proverb count")
9
10
11
12
13
// 3. Ausgabe in Schleife
14
for i := 0; i < *count; i++ {
15
var p *proverbs.Proverb = proverbs.Random()
16
fmt.Println(p.Saying)
17
}
18
}
19
// 3. Ausgabe in Schleife
for i := 0; i < *count; i++ {
var p *proverbs.Proverb = proverbs.Random()
fmt.Println(p.Saying)
}
import (
1
"flag"
2
"fmt"
3
"github.com/jboursiquot/go-proverbs"
4
)
5
6
func main() {
7
// 1. Flags definieren
8
var count *int = flag.Int("count", 1, "proverb count")
9
10
// 2. Flags parsen
11
flag.Parse()
12
13
14
15
16
17
18
}
19
import (
"flag"
"fmt"
"github.com/jboursiquot/go-proverbs"
)
func main() {
// 1. Flags definieren
var count *int = flag.Int("count", 1, "proverb count")
// 2. Flags parsen
flag.Parse()
// 3. Ausgabe in Schleife
for i := 0; i < *count; i++ {
var p *proverbs.Proverb = proverbs.Random()
fmt.Println(p.Saying)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Compile mit `go build .`, Ausgabe mit `pro -count=2`
Make the zero value useful.
Reflection is never clear.
CLI Proverbs mit ungültigem Count
> pro -count=
flag needs an argument: -count
Usage of ./pro:
-count int
proverb count (default 1)
Flag fürCount Refactored
count := flag.Int("count", 1, "proverb count")
p := proverbs.Random()
import (
1
"flag"
2
"fmt"
3
"github.com/jboursiquot/go-proverbs"
4
)
5
6
func main() {
7
// 1. Flags definieren
8
9
10
// 2. Flags parsen
11
flag.Parse()
12
13
// 3. Ausgabe in Schleife
14
for range *count {
15
16
fmt.Println(p.Saying)
17
}
18
}
19
for range *count {
}
import (
1
"flag"
2
"fmt"
3
"github.com/jboursiquot/go-proverbs"
4
)
5
6
func main() {
7
// 1. Flags definieren
8
count := flag.Int("count", 1, "proverb count")
9
10
// 2. Flags parsen
11
flag.Parse()
12
13
// 3. Ausgabe in Schleife
14
15
p := proverbs.Random()
16
fmt.Println(p.Saying)
17
18
}
19
import (
"flag"
"fmt"
"github.com/jboursiquot/go-proverbs"
)
func main() {
// 1. Flags definieren
count := flag.Int("count", 1, "proverb count")
// 2. Flags parsen
flag.Parse()
// 3. Ausgabe in Schleife
for range *count {
p := proverbs.Random()
fmt.Println(p.Saying)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Compile mit `go build .`, Ausgabe mit `pro -count=2`
Make the zero value useful.
Reflection is never clear.
🖥️CLI Tool
File Downloader
File Downloader
ParallelerFile Download
#
Nutzt Goroutinen und Channels
#
Context is King
#
File Downloader1/3
func main() {
urls := []string{
"https://go.dev/dl/go1.22.2.src.tar.gz",
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
}
}
1
2
3
4
5
6
// URL Download
7
ctx := context.Background()
8
downloadURLs(ctx, urls)
9
10
11
func downloadURLs(ctx context.Context, urls []string) {
12
// ...
13
}
14
func main() {
urls := []string{
"https://go.dev/dl/go1.22.2.src.tar.gz",
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
}
}
1
2
3
4
5
6
// URL Download
7
ctx := context.Background()
8
downloadURLs(ctx, urls)
9
10
11
func downloadURLs(ctx context.Context, urls []string) {
12
// ...
13
}
14
func main() {
// URL Download
ctx := context.Background()
downloadURLs(ctx, urls)
}
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
7
8
9
10
11
func downloadURLs(ctx context.Context, urls []string) {
12
// ...
13
}
14
func main() {
urls := []string{
"https://go.dev/dl/go1.22.2.src.tar.gz",
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
}
// URL Download
ctx := context.Background()
downloadURLs(ctx, urls)
}
func downloadURLs(ctx context.Context, urls []string) {
// ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
File Downloader2/3
// 1. Channel für Download Jobs
jobs := make(chan int, len(urls))
func downloadURLs(ctx context.Context, urls []string) {
1
2
3
4
// 2. Go Routinen für Downloads starten
5
for _, url := range urls {
6
go func() {
7
downloadURL(ctx, url)
8
jobs <- 1 // Send an Channel (blockiert)
9
}()
10
}
11
12
// 3. Warten auf Ende aller Go Routinen
13
for range len(urls) {
14
<-jobs // Receive von Channel (blockiert)
15
}
16
}
17
// 2. Go Routinen für Downloads starten
for _, url := range urls {
go func() {
downloadURL(ctx, url)
jobs <- 1 // Send an Channel (blockiert)
}()
}
func downloadURLs(ctx context.Context, urls []string) {
1
// 1. Channel für Download Jobs
2
jobs := make(chan int, len(urls))
3
4
5
6
7
8
9
10
11
12
// 3. Warten auf Ende aller Go Routinen
13
for range len(urls) {
14
<-jobs // Receive von Channel (blockiert)
15
}
16
}
17
// 3. Warten auf Ende aller Go Routinen
for range len(urls) {
<-jobs // Receive von Channel (blockiert)
}
func downloadURLs(ctx context.Context, urls []string) {
1
// 1. Channel für Download Jobs
2
jobs := make(chan int, len(urls))
3
4
// 2. Go Routinen für Downloads starten
5
for _, url := range urls {
6
go func() {
7
downloadURL(ctx, url)
8
jobs <- 1 // Send an Channel (blockiert)
9
}()
10
}
11
12
13
14
15
16
}
17
func downloadURLs(ctx context.Context, urls []string) {
// 1. Channel für Download Jobs
jobs := make(chan int, len(urls))
// 2. Go Routinen für Downloads starten
for _, url := range urls {
go func() {
downloadURL(ctx, url)
jobs <- 1 // Send an Channel (blockiert)
}()
}
// 3. Warten auf Ende aller Go Routinen
for range len(urls) {
<-jobs // Receive von Channel (blockiert)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
File Downloader3/3
func downloadURL(ctx context.Context, url string) {
// 1. HTTP Request mit Context erstellen
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
1
2
3
4
// 2. HTTP Aufruf durchführen
5
httpClient := http.Client{}
6
resp, _ := httpClient.Do(req)
7
defer resp.Body.Close()
8
9
// 3. Ausgabe in Datei
10
file, _ := os.Create(filepath.Base(url))
11
defer file.Close()
12
13
// 4. HTTP Body in Datei streamen
14
io.Copy(file, resp.Body)
15
}
16
// 2. HTTP Aufruf durchführen
httpClient := http.Client{}
resp, _ := httpClient.Do(req)
defer resp.Body.Close()
func downloadURL(ctx context.Context, url string) {
1
// 1. HTTP Request mit Context erstellen
2
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
3
4
5
6
7
8
9
// 3. Ausgabe in Datei
10
file, _ := os.Create(filepath.Base(url))
11
defer file.Close()
12
13
// 4. HTTP Body in Datei streamen
14
io.Copy(file, resp.Body)
15
}
16
// 3. Ausgabe in Datei
file, _ := os.Create(filepath.Base(url))
defer file.Close()
func downloadURL(ctx context.Context, url string) {
1
// 1. HTTP Request mit Context erstellen
2
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
3
4
// 2. HTTP Aufruf durchführen
5
httpClient := http.Client{}
6
resp, _ := httpClient.Do(req)
7
defer resp.Body.Close()
8
9
10
11
12
13
// 4. HTTP Body in Datei streamen
14
io.Copy(file, resp.Body)
15
}
16
// 4. HTTP Body in Datei streamen
io.Copy(file, resp.Body)
func downloadURL(ctx context.Context, url string) {
1
// 1. HTTP Request mit Context erstellen
2
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
3
4
// 2. HTTP Aufruf durchführen
5
httpClient := http.Client{}
6
resp, _ := httpClient.Do(req)
7
defer resp.Body.Close()
8
9
// 3. Ausgabe in Datei
10
file, _ := os.Create(filepath.Base(url))
11
defer file.Close()
12
13
14
15
}
16
func downloadURL(ctx context.Context, url string) {
// 1. HTTP Request mit Context erstellen
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
// 2. HTTP Aufruf durchführen
httpClient := http.Client{}
resp, _ := httpClient.Do(req)
defer resp.Body.Close()
// 3. Ausgabe in Datei
file, _ := os.Create(filepath.Base(url))
defer file.Close()
// 4. HTTP Body in Datei streamen
io.Copy(file, resp.Body)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
File Downloader3/3 mit Fehlern
func downloadURL(ctx context.Context, url string) error {
}
1
// 1. HTTP Request mit Context erstellen
2
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
3
if err != nil {
4
return err
5
}
6
7
// 2. HTTP Aufruf durchführen
8
// ...
9
10
// 1. HTTP Request mit Context erstellen
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return err
}
func downloadURL(ctx context.Context, url string) error {
1
2
3
4
5
6
7
// 2. HTTP Aufruf durchführen
8
// ...
9
}
10
func downloadURL(ctx context.Context, url string) error {
// 1. HTTP Request mit Context erstellen
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return err
}
// 2. HTTP Aufruf durchführen
// ...
}
1
2
3
4
5
6
7
8
9
10
File Downloadermit Timeout
// 1. Context mit Cancel Func
ctx, cancel := context.WithCancel(context.Background())
// 3. URL Download
downloadURLs(ctx, urls)
func main() {
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
7
8
9
// 2. Timer Channel nutzen
10
timer := time.After(3 * time.Second)
11
go func() {
12
<-timer // Receive timer Channel
13
log.Println("Canceled due to timeout")
14
cancel()
15
}()
16
17
18
19
}
20
// 2. Timer Channel nutzen
timer := time.After(3 * time.Second)
go func() {
<-timer // Receive timer Channel
log.Println("Canceled due to timeout")
cancel()
}()
func main() {
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
// 1. Context mit Cancel Func
7
ctx, cancel := context.WithCancel(context.Background())
8
9
10
11
12
13
14
15
16
17
// 3. URL Download
18
downloadURLs(ctx, urls)
19
}
20
// 1. Context mit Cancel Func
ctx, cancel := context.WithCancel(context.Background())
// 2. Timer Channel nutzen
timer := time.After(3 * time.Second)
go func() {
<-timer // Receive timer Channel
log.Println("Canceled due to timeout")
cancel()
}()
// 3. URL Download
downloadURLs(ctx, urls)
func main() {
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
}
20
File Downloadermit Interrupt
// 1. Context mit Cancel Func
ctx, cancel := context.WithCancel(context.Background())
// 3. URL Download
downloadURLs(ctx, urls)
func main() {
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
7
8
9
// 2. Interrupt Channel nutzen
10
interrupt := make(chan os.Signal, 1)
11
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
12
go func() {
13
<-interrupt // Receive interrupt Channel
14
log.Println("Canceled due to interrupt")
15
cancel()
16
}()
17
18
19
20
}
21
// 2. Interrupt Channel nutzen
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
go func() {
<-interrupt // Receive interrupt Channel
log.Println("Canceled due to interrupt")
cancel()
}()
func main() {
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
// 1. Context mit Cancel Func
7
ctx, cancel := context.WithCancel(context.Background())
8
9
10
11
12
13
14
15
16
17
18
// 3. URL Download
19
downloadURLs(ctx, urls)
20
}
21
// 1. Context mit Cancel Func
ctx, cancel := context.WithCancel(context.Background())
// 2. Interrupt Channel nutzen
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
go func() {
<-interrupt // Receive interrupt Channel
log.Println("Canceled due to interrupt")
cancel()
}()
// 3. URL Download
downloadURLs(ctx, urls)
func main() {
1
urls := []string{
2
"https://go.dev/dl/go1.22.2.src.tar.gz",
3
"https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz",
4
}
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
}
21
File Downloadermit Select
// 1. Context mit Cancel Func
// + Timeout Channel
// + Interrupt Channel
func main() {
1
2
3
4
5
go func() {
6
select {
7
// 2a. Receive timer Channel
8
case <-timer:
9
log.Println("Canceled due to timeout")
10
cancel()
11
// 2b. Receive interrupt Channel
12
case <-interrupt:
13
log.Println("Canceled due to interrupt")
14
cancel()
15
}
16
}()
17
18
// 3. URL Download
19
downloadURLs(ctx, urls)
20
}
21
select {
// 2a. Receive timer Channel
case <-timer:
log.Println("Canceled due to timeout")
cancel()
}
func main() {
1
// 1. Context mit Cancel Func
2
// + Timeout Channel
3
// + Interrupt Channel
4
5
go func() {
6
7
8
9
10
11
// 2b. Receive interrupt Channel
12
case <-interrupt:
13
log.Println("Canceled due to interrupt")
14
cancel()
15
16
}()
17
18
// 3. URL Download
19
downloadURLs(ctx, urls)
20
}
21
select {
// 2b. Receive interrupt Channel
case <-interrupt:
log.Println("Canceled due to interrupt")
cancel()
}
func main() {
1
// 1. Context mit Cancel Func
2
// + Timeout Channel
3
// + Interrupt Channel
4
5
go func() {
6
7
// 2a. Receive timer Channel
8
case <-timer:
9
log.Println("Canceled due to timeout")
10
cancel()
11
12
13
14
15
16
}()
17
18
// 3. URL Download
19
downloadURLs(ctx, urls)
20
}
21
select {
// 2a. Receive timer Channel
case <-timer:
log.Println("Canceled due to timeout")
cancel()
// 2b. Receive interrupt Channel
case <-interrupt:
log.Println("Canceled due to interrupt")
cancel()
}
func main() {
1
// 1. Context mit Cancel Func
2
// + Timeout Channel
3
// + Interrupt Channel
4
5
go func() {
6
7
8
9
10
11
12
13
14
15
16
}()
17
18
// 3. URL Download
19
downloadURLs(ctx, urls)
20
}
21
🖥️CLI Tools
Standardlib Flags
#
einfache Releases mit Goreleaser
#
Cobra CLI Lib wenn's komplexerwird
#
Github, Kubernetes sind Go CLIs
#
🌐Web App Cats
Set up Cats App
# 1. Verzeichnis erstellen
mkdir cats
cd cats
# 2. Go Modul aufsetzen
go mod init crossnative.com/cats
# 3. Go Datei erstellen
touch main.go
Cat API simple
func main() {
http.HandleFunc("GET /api/cats", catAPIHandler)
http.ListenAndServe(":8080", nil)
}
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
1
fmt.Fprintf(w, "Meow!")
2
w.WriteHeader(http.StatusOK)
3
}
4
5
6
7
8
9
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Meow!")
w.WriteHeader(http.StatusOK)
}
1
2
3
4
5
func main() {
6
http.HandleFunc("GET /api/cats", catAPIHandler)
7
http.ListenAndServe(":8080", nil)
8
}
9
Cat API mit JSON
// 1. Struct mit JSON Tag definieren
type Cat struct {
Name string `json:"name"`
}
1
2
3
4
5
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
6
// 2. Slice erstellen
7
cats := make([]Cat, 1)
8
9
// 3. Struct erstellen und einfügen
10
cats[0] = Cat{Name: "Ginger"}
11
12
// 4. JSON rendern
13
json.NewEncoder(w).Encode(cats)
14
}
15
16
func main() {
17
http.HandleFunc("GET /api/cats", catAPIHandler)
18
http.ListenAndServe(":8080", nil)
19
}
20
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
}
// 1. Struct mit JSON Tag definieren
1
type Cat struct {
2
Name string `json:"name"`
3
}
4
5
6
// 2. Slice erstellen
7
cats := make([]Cat, 1)
8
9
// 3. Struct erstellen und einfügen
10
cats[0] = Cat{Name: "Ginger"}
11
12
// 4. JSON rendern
13
json.NewEncoder(w).Encode(cats)
14
15
16
func main() {
17
http.HandleFunc("GET /api/cats", catAPIHandler)
18
http.ListenAndServe(":8080", nil)
19
}
20
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
// 2. Slice erstellen
cats := make([]Cat, 1)
}
// 1. Struct mit JSON Tag definieren
1
type Cat struct {
2
Name string `json:"name"`
3
}
4
5
6
7
8
9
// 3. Struct erstellen und einfügen
10
cats[0] = Cat{Name: "Ginger"}
11
12
// 4. JSON rendern
13
json.NewEncoder(w).Encode(cats)
14
15
16
func main() {
17
http.HandleFunc("GET /api/cats", catAPIHandler)
18
http.ListenAndServe(":8080", nil)
19
}
20
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
// 3. Struct erstellen und einfügen
cats[0] = Cat{Name: "Ginger"}
}
// 1. Struct mit JSON Tag definieren
1
type Cat struct {
2
Name string `json:"name"`
3
}
4
5
6
// 2. Slice erstellen
7
cats := make([]Cat, 1)
8
9
10
11
12
// 4. JSON rendern
13
json.NewEncoder(w).Encode(cats)
14
15
16
func main() {
17
http.HandleFunc("GET /api/cats", catAPIHandler)
18
http.ListenAndServe(":8080", nil)
19
}
20
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
// 4. JSON rendern
json.NewEncoder(w).Encode(cats)
}
// 1. Struct mit JSON Tag definieren
1
type Cat struct {
2
Name string `json:"name"`
3
}
4
5
6
// 2. Slice erstellen
7
cats := make([]Cat, 1)
8
9
// 3. Struct erstellen und einfügen
10
cats[0] = Cat{Name: "Ginger"}
11
12
13
14
15
16
func main() {
17
http.HandleFunc("GET /api/cats", catAPIHandler)
18
http.ListenAndServe(":8080", nil)
19
}
20
// 1. Struct mit JSON Tag definieren
type Cat struct {
Name string `json:"name"`
}
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
// 2. Slice erstellen
cats := make([]Cat, 1)
// 3. Struct erstellen und einfügen
cats[0] = Cat{Name: "Ginger"}
// 4. JSON rendern
json.NewEncoder(w).Encode(cats)
}
func main() {
http.HandleFunc("GET /api/cats", catAPIHandler)
http.ListenAndServe(":8080", nil)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Cat API mit JSON
# Query cat API
curl -s http://localhost:8080/api/cats | jq
1
2
[
3
{
4
"name": "Ginger"
5
}
6
]
7
[
{
"name": "Ginger"
}
]
# Query cat API
1
curl -s http://localhost:8080/api/cats | jq
2
3
4
5
6
7
Test Cat API cat_api_test.go
func TestCatAPIHandler(t *testing.T) {
}
1
// 1. Test Request erstellen
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
// 2. HTTP Recorder erstellen (ist http.ResponseWriter)
5
rec := httptest.NewRecorder()
6
7
// 3. Handler aufrufen
8
catAPIHandler(rec, req)
9
10
// 4. Response prüfen
11
if rec.Code != http.StatusOK {
12
t.Errorf("got status %v expected %v", rec.Code, http.StatusOK)
13
}
14
15
// 1. Test Request erstellen
req, _ := http.NewRequest("GET", "/api/cats", nil)
func TestCatAPIHandler(t *testing.T) {
1
2
3
4
// 2. HTTP Recorder erstellen (ist http.ResponseWriter)
5
rec := httptest.NewRecorder()
6
7
// 3. Handler aufrufen
8
catAPIHandler(rec, req)
9
10
// 4. Response prüfen
11
if rec.Code != http.StatusOK {
12
t.Errorf("got status %v expected %v", rec.Code, http.StatusOK)
13
}
14
}
15
// 2. HTTP Recorder erstellen (ist http.ResponseWriter)
rec := httptest.NewRecorder()
func TestCatAPIHandler(t *testing.T) {
1
// 1. Test Request erstellen
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
5
6
7
// 3. Handler aufrufen
8
catAPIHandler(rec, req)
9
10
// 4. Response prüfen
11
if rec.Code != http.StatusOK {
12
t.Errorf("got status %v expected %v", rec.Code, http.StatusOK)
13
}
14
}
15
// 3. Handler aufrufen
catAPIHandler(rec, req)
func TestCatAPIHandler(t *testing.T) {
1
// 1. Test Request erstellen
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
// 2. HTTP Recorder erstellen (ist http.ResponseWriter)
5
rec := httptest.NewRecorder()
6
7
8
9
10
// 4. Response prüfen
11
if rec.Code != http.StatusOK {
12
t.Errorf("got status %v expected %v", rec.Code, http.StatusOK)
13
}
14
}
15
// 4. Response prüfen
if rec.Code != http.StatusOK {
t.Errorf("got status %v expected %v", rec.Code, http.StatusOK)
}
func TestCatAPIHandler(t *testing.T) {
1
// 1. Test Request erstellen
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
// 2. HTTP Recorder erstellen (ist http.ResponseWriter)
5
rec := httptest.NewRecorder()
6
7
// 3. Handler aufrufen
8
catAPIHandler(rec, req)
9
10
11
12
13
14
}
15
func TestCatAPIHandler(t *testing.T) {
// 1. Test Request erstellen
req, _ := http.NewRequest("GET", "/api/cats", nil)
// 2. HTTP Recorder erstellen (ist http.ResponseWriter)
rec := httptest.NewRecorder()
// 3. Handler aufrufen
catAPIHandler(rec, req)
// 4. Response prüfen
if rec.Code != http.StatusOK {
t.Errorf("got status %v expected %v", rec.Code, http.StatusOK)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Test ausführen
go test -v ./...
1
=== RUN TestCatAPIHandler
2
--- PASS: TestCatAPIHandler (0.00s)
3
PASS
4
coverage: 50.0% of statements
5
ok crossnative.com/cats 0.127s coverage: 50.0% of statements
6
=== RUN TestCatAPIHandler
--- PASS: TestCatAPIHandler (0.00s)
PASS
coverage: 50.0% of statements
ok crossnative.com/cats 0.127s coverage: 50.0% of statements
go test -v ./...
1
2
3
4
5
6
Cats App
Web
Cats Web App
// 1. Mulitplexer erzeugen
mux := http.NewServeMux()
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
tpl := template.Must(template.ParseFiles("index.html"))
2
tpl.Execute(w, nil)
3
}
4
5
func main() {
6
7
8
9
// 2. Handler registrieren
10
mux.HandleFunc("/", indexHandler)
11
12
// 3. Server mit Mulitplexer starten
13
http.ListenAndServe(":8080", mux)
14
}
15
// 2. Handler registrieren
mux.HandleFunc("/", indexHandler)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
tpl := template.Must(template.ParseFiles("index.html"))
2
tpl.Execute(w, nil)
3
}
4
5
func main() {
6
// 1. Mulitplexer erzeugen
7
mux := http.NewServeMux()
8
9
10
11
12
// 3. Server mit Mulitplexer starten
13
http.ListenAndServe(":8080", mux)
14
}
15
// 3. Server mit Mulitplexer starten
http.ListenAndServe(":8080", mux)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
tpl := template.Must(template.ParseFiles("index.html"))
2
tpl.Execute(w, nil)
3
}
4
5
func main() {
6
// 1. Mulitplexer erzeugen
7
mux := http.NewServeMux()
8
9
// 2. Handler registrieren
10
mux.HandleFunc("/", indexHandler)
11
12
13
14
}
15
func indexHandler(w http.ResponseWriter, r *http.Request) {
tpl := template.Must(template.ParseFiles("index.html"))
tpl.Execute(w, nil)
}
func main() {
// 1. Mulitplexer erzeugen
mux := http.NewServeMux()
// 2. Handler registrieren
mux.HandleFunc("/", indexHandler)
// 3. Server mit Mulitplexer starten
http.ListenAndServe(":8080", mux)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
File Serveraus Binary
//go:embed assets
var assets embed.FS
// Serve Files
mux.Handle("/assets/", http.FileServer(http.FS(assets)))
1
2
3
func main() {
4
mux := http.NewServeMux()
5
mux.HandleFunc("/", indexHandler)
6
7
8
9
10
http.ListenAndServe(":8080", mux)
11
}
12
Index HandlerTemplate mit Daten
type Cat struct {
Name string
}
func indexHandler(w ResponseWriter, r *Request) {
// 1. Slice erstellen
cat := make([]Cat, 1)
// 2. Struct erstellen und einfügen
cat[0] = Cat{Name: "Ginger"}
// 3. Template rendern
tpl := template.Must(template.ParseFiles("index.html"))
tpl.Execute(w, cat)
}
<body>
<h1>Cats App</h1>
{{ range . }}
<h2>{{ .Name }}</h2>
{{ end }}
</body>
Index Handlermit Cats API
Query Cats API
GET https://api.thecatapi.com/v1/breeds?limit=5
[
{
"id": "abys",
"name": "Abyssinian",
"image": {
"url": "https://cdn2.thecatapi.com/0XYvRd7oD.jpg"
}
},
{
"id": "aege",
"name": "Aegean",
"image": {
"url": "https://cdn2.thecatapi.com/ozEvzdVM-.jpg"
}
},
...
]
Map JSON auf Struct
type Cat struct {
ID string `json:"id"`
Name string `json:"name"`
Image struct {
URL string `json:"url"`
} `json:"image"`
}
Index Handlermit Cats API
// 1. Cat API Aufruf (Fehler ignorieren)
resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
2
3
4
// 2. Slice für Cat Structs
5
cat := make([]Cat, 5)
6
7
// 3. Response Body parsen
8
defer resp.Body.Close()
9
body, _ := ioutil.ReadAll(resp.Body)
10
json.Unmarshal(body, &cat)
11
12
// 4. Template rendern
13
tpl.Execute(w, cat)
14
}
15
// 2. Slice für Cat Structs
cat := make([]Cat, 5)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
// 1. Cat API Aufruf (Fehler ignorieren)
2
resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
3
4
5
6
7
// 3. Response Body parsen
8
defer resp.Body.Close()
9
body, _ := ioutil.ReadAll(resp.Body)
10
json.Unmarshal(body, &cat)
11
12
// 4. Template rendern
13
tpl.Execute(w, cat)
14
}
15
// 3. Response Body parsen
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
json.Unmarshal(body, &cat)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
// 1. Cat API Aufruf (Fehler ignorieren)
2
resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
3
4
// 2. Slice für Cat Structs
5
cat := make([]Cat, 5)
6
7
8
9
10
11
12
// 4. Template rendern
13
tpl.Execute(w, cat)
14
}
15
// 4. Template rendern
tpl.Execute(w, cat)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
// 1. Cat API Aufruf (Fehler ignorieren)
2
resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
3
4
// 2. Slice für Cat Structs
5
cat := make([]Cat, 5)
6
7
// 3. Response Body parsen
8
defer resp.Body.Close()
9
body, _ := ioutil.ReadAll(resp.Body)
10
json.Unmarshal(body, &cat)
11
12
13
14
}
15
func indexHandler(w http.ResponseWriter, r *http.Request) {
// 1. Cat API Aufruf (Fehler ignorieren)
resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
// 2. Slice für Cat Structs
cat := make([]Cat, 5)
// 3. Response Body parsen
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
json.Unmarshal(body, &cat)
// 4. Template rendern
tpl.Execute(w, cat)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Index Handlermit Fehlerhandling 💣
// 1. Cat API Aufruf
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
2
3
// Fehler behandeln
4
if err != nil {
5
http.Error(w, "Cats API error", http.StatusInternalServerError)
6
return
7
}
8
9
// 2. Slice für Cat Structs
10
cat := make([]Cat, 5)
11
12
// 3. Response Body parsen
13
defer resp.Body.Close()
14
body, _ := ioutil.ReadAll(resp.Body)
15
err := json.Unmarshal(body, &cat)
16
// TODO: Fehler behandeln
17
18
// 4. Template rendern
19
err := tpl.Execute(w, cat)
20
// TODO: Fehler behandeln
21
}
22
// Fehler behandeln
if err != nil {
http.Error(w, "Cats API error", http.StatusInternalServerError)
return
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
// 1. Cat API Aufruf
2
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
3
4
5
6
7
8
9
// 2. Slice für Cat Structs
10
cat := make([]Cat, 5)
11
12
// 3. Response Body parsen
13
defer resp.Body.Close()
14
body, _ := ioutil.ReadAll(resp.Body)
15
err := json.Unmarshal(body, &cat)
16
// TODO: Fehler behandeln
17
18
// 4. Template rendern
19
err := tpl.Execute(w, cat)
20
// TODO: Fehler behandeln
21
}
22
// 1. Cat API Aufruf
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
// Fehler behandeln
if err != nil {
http.Error(w, "Cats API error", http.StatusInternalServerError)
return
}
err := json.Unmarshal(body, &cat)
// TODO: Fehler behandeln
err := tpl.Execute(w, cat)
// TODO: Fehler behandeln
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
2
3
4
5
6
7
8
9
// 2. Slice für Cat Structs
10
cat := make([]Cat, 5)
11
12
// 3. Response Body parsen
13
defer resp.Body.Close()
14
body, _ := ioutil.ReadAll(resp.Body)
15
16
17
18
// 4. Template rendern
19
20
21
}
22
🌐Web App
Standardlib JSON und Router
#
HTTPTests
#
Querschnittsfeatures durch Middleware
#
λ Lambda Function
λ Lambda Function
Go ideal fürServerless Functions
#
schnellerStart, geringerSpeicherbedarf
#
unterstützt von AWS, Azure, Google
#
λ Lambda Function
λ Lambda Function
// 1. Lambda Go Projekt aufsetzen
> sam init
1
2
3
// 2. Lambda bauen
4
> sam build
5
6
// 3. Lambda ausführen
7
> sam local invoke -e events/event.json
8
Invoking bootstrap (provided.al2023)
9
Local image is up-to-date
10
Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64.
11
12
Mounting .aws-sam/build/HelloWorldFunction, inside runtime container
13
REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms
14
Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB
15
{"statusCode": 200, "body": "Hello JAX!"}
16
// 2. Lambda bauen
> sam build
// 1. Lambda Go Projekt aufsetzen
1
> sam init
2
3
4
5
6
// 3. Lambda ausführen
7
> sam local invoke -e events/event.json
8
Invoking bootstrap (provided.al2023)
9
Local image is up-to-date
10
Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64.
11
12
Mounting .aws-sam/build/HelloWorldFunction, inside runtime container
13
REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms
14
Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB
15
{"statusCode": 200, "body": "Hello JAX!"}
16
// 3. Lambda ausführen
> sam local invoke -e events/event.json
Invoking bootstrap (provided.al2023)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64.
Mounting .aws-sam/build/HelloWorldFunction, inside runtime container
REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms
Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "Hello JAX!"}
// 1. Lambda Go Projekt aufsetzen
1
> sam init
2
3
// 2. Lambda bauen
4
> sam build
5
6
7
8
9
10
11
12
13
14
15
16
// 1. Lambda Go Projekt aufsetzen
> sam init
// 2. Lambda bauen
> sam build
// 3. Lambda ausführen
> sam local invoke -e events/event.json
Invoking bootstrap (provided.al2023)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64.
Mounting .aws-sam/build/HelloWorldFunction, inside runtime container
REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms
Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "Hello JAX!"}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
λ Lambda Function
λ Lambda Function
# Query AWS Lambda
curl -s https://0up9.eu-north-1.amazonaws.com/Prod/hello
1
2
Hello JAX!
3 Hello JAX!
# Query AWS Lambda
1
curl -s https://0up9.eu-north-1.amazonaws.com/Prod/hello
2
3
Footprint
Package Size 5,3 MB
Billed Duration 70 ms
Max Memory Used 18 MB
Init Duration 63.66 ms
#
#
#
#
λ Lambda Function
func main() {
lambda.Start(handler)
}
import (
1
"fmt"
2
"github.com/aws/aws-lambda-go/events"
3
"github.com/aws/aws-lambda-go/lambda"
4
)
5
6
func handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
7
return events.APIGatewayProxyResponse{
8
Body: "Hello JAX!",
9
StatusCode: 200,
10
}, nil
11
}
12
13
14
15
16
func handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
return events.APIGatewayProxyResponse{
Body: "Hello JAX!",
StatusCode: 200,
}, nil
}
import (
1
"fmt"
2
"github.com/aws/aws-lambda-go/events"
3
"github.com/aws/aws-lambda-go/lambda"
4
)
5
6
7
8
9
10
11
12
13
func main() {
14
lambda.Start(handler)
15
}
16
import (
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
return events.APIGatewayProxyResponse{
Body: "Hello JAX!",
StatusCode: 200,
}, nil
}
func main() {
lambda.Start(handler)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
λ Lambda Function Projekt
|-events
| event.json // Beispiel Request
|-hello-world // Go App
| go.mod
| go.sum
| main.go
| main_test.go
| Makefile // Build File
| samconfig.toml // SAM Config
| template.yaml // SAM Config
| README.md
🖥️CLI Tools
Projekt Setup
Variablen,
Schleifen
Goroutinen,
Channels
Context
Structs
#
#
#
#
#
🌐Web App
Web Server
Slice
Unit Test
JSON
Fehlerhandling
#
#
#
#
#
λ Lambda Func
AWS Setup
Serverless
Experience
#
#
3 Gründe fürGo
1. Einfach
2. Mächtig
3. Langweilig
Go liebt
Microservices Serverless Functions
Kommandozeilen-Tools DevOps und Cloud
Jan Stamer
jan.stamer@crossnative.com
Go in derPraxis

More Related Content

Similar to JAX 2024: Go in der Praxis einsetzen

Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoFrank Müller
 
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...NETWAYS
 
Entwicklungsumgebungen mit Vagrant
Entwicklungsumgebungen mit VagrantEntwicklungsumgebungen mit Vagrant
Entwicklungsumgebungen mit VagrantB1 Systems GmbH
 
Modern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_scriptModern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_scriptManfred Steyer
 
Tech Talk: Groovy
Tech Talk: GroovyTech Talk: Groovy
Tech Talk: Groovymwie
 
Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...
Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...
Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...NETWAYS
 
OSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas Lange
OSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas LangeOSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas Lange
OSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas LangeNETWAYS
 
W-JAX 2023: Go über den Wolken
W-JAX 2023: Go über den WolkenW-JAX 2023: Go über den Wolken
W-JAX 2023: Go über den WolkenJan Stamer
 
OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...
OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...
OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...NETWAYS
 
SLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauenSLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauenSchlomo Schapiro
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in GoFrank Müller
 
SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen
SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgenSEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen
SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgenDr. Herwig Henseler
 
OSDC 2011 | FAI - Fully Automatic Installation by Thomas Lange
OSDC 2011 | FAI - Fully Automatic Installation by Thomas LangeOSDC 2011 | FAI - Fully Automatic Installation by Thomas Lange
OSDC 2011 | FAI - Fully Automatic Installation by Thomas LangeNETWAYS
 
Check cisco voice
Check cisco voiceCheck cisco voice
Check cisco voicebboguhn
 
Python Enterprise Apllication Toolkit (PEAK) - Eine kurze Einführung
Python Enterprise Apllication Toolkit (PEAK) - Eine kurze EinführungPython Enterprise Apllication Toolkit (PEAK) - Eine kurze Einführung
Python Enterprise Apllication Toolkit (PEAK) - Eine kurze Einführungrjtg
 

Similar to JAX 2024: Go in der Praxis einsetzen (20)

Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google Go
 
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
 
Entwicklungsumgebungen mit Vagrant
Entwicklungsumgebungen mit VagrantEntwicklungsumgebungen mit Vagrant
Entwicklungsumgebungen mit Vagrant
 
Modern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_scriptModern angular 02_angular_mit_type_script
Modern angular 02_angular_mit_type_script
 
Tech Talk: Groovy
Tech Talk: GroovyTech Talk: Groovy
Tech Talk: Groovy
 
Versionskontrolle mit Git
Versionskontrolle mit GitVersionskontrolle mit Git
Versionskontrolle mit Git
 
Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...
Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...
Nagios Conference 2007 | Monitoring von Logfiles mit check_logfiles by Gerhar...
 
Grunt
GruntGrunt
Grunt
 
OSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas Lange
OSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas LangeOSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas Lange
OSDC 2010 | FAI - ein Projekt wird 10 Jahre alt by Thomas Lange
 
Bottle - Python Web Microframework
Bottle - Python Web MicroframeworkBottle - Python Web Microframework
Bottle - Python Web Microframework
 
W-JAX 2023: Go über den Wolken
W-JAX 2023: Go über den WolkenW-JAX 2023: Go über den Wolken
W-JAX 2023: Go über den Wolken
 
OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...
OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...
OSMC 2010 | Verwendung von Puppet in verteilten Monitoring Umgebungen by Birg...
 
Web Entwicklung mit PHP - Teil 2
Web Entwicklung mit PHP - Teil 2Web Entwicklung mit PHP - Teil 2
Web Entwicklung mit PHP - Teil 2
 
SLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauenSLAC 2008 RPMs selber bauen
SLAC 2008 RPMs selber bauen
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in Go
 
Ein Gopher im Netz
Ein Gopher im NetzEin Gopher im Netz
Ein Gopher im Netz
 
SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen
SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgenSEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen
SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen
 
OSDC 2011 | FAI - Fully Automatic Installation by Thomas Lange
OSDC 2011 | FAI - Fully Automatic Installation by Thomas LangeOSDC 2011 | FAI - Fully Automatic Installation by Thomas Lange
OSDC 2011 | FAI - Fully Automatic Installation by Thomas Lange
 
Check cisco voice
Check cisco voiceCheck cisco voice
Check cisco voice
 
Python Enterprise Apllication Toolkit (PEAK) - Eine kurze Einführung
Python Enterprise Apllication Toolkit (PEAK) - Eine kurze EinführungPython Enterprise Apllication Toolkit (PEAK) - Eine kurze Einführung
Python Enterprise Apllication Toolkit (PEAK) - Eine kurze Einführung
 

More from Jan Stamer

JAX 2024: Go-über-den-Wolken und in der Cloud
JAX 2024: Go-über-den-Wolken und in der CloudJAX 2024: Go-über-den-Wolken und in der Cloud
JAX 2024: Go-über-den-Wolken und in der CloudJan Stamer
 
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. JavaCloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. JavaJan Stamer
 
entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101Jan Stamer
 
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystembetterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystemJan Stamer
 
JCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web AppsJCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web AppsJan Stamer
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101Jan Stamer
 
JavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
JavaForum Nord 2021: Java to Go - Google Go für Java-EntwicklerJavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
JavaForum Nord 2021: Java to Go - Google Go für Java-EntwicklerJan Stamer
 
Karlsruher Entwicklertag 2021: Turbo powered Web Apps
Karlsruher Entwicklertag 2021: Turbo powered Web AppsKarlsruher Entwicklertag 2021: Turbo powered Web Apps
Karlsruher Entwicklertag 2021: Turbo powered Web AppsJan Stamer
 
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?Jan Stamer
 

More from Jan Stamer (9)

JAX 2024: Go-über-den-Wolken und in der Cloud
JAX 2024: Go-über-den-Wolken und in der CloudJAX 2024: Go-über-den-Wolken und in der Cloud
JAX 2024: Go-über-den-Wolken und in der Cloud
 
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. JavaCloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
 
entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101entwickler.de Go Day: Go Web Development 101
entwickler.de Go Day: Go Web Development 101
 
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und ÖkosystembetterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
 
JCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web AppsJCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web Apps
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101
 
JavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
JavaForum Nord 2021: Java to Go - Google Go für Java-EntwicklerJavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
JavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
 
Karlsruher Entwicklertag 2021: Turbo powered Web Apps
Karlsruher Entwicklertag 2021: Turbo powered Web AppsKarlsruher Entwicklertag 2021: Turbo powered Web Apps
Karlsruher Entwicklertag 2021: Turbo powered Web Apps
 
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
 

JAX 2024: Go in der Praxis einsetzen

  • 2.
  • 3. gh Github CLI 149.298 Zeilen Code 490 Contributors
  • 4. 1. 🖥️ CLI Tools 2. 🌐 Web App 3. λ Lambda Function
  • 5. 5 Fakten zu Go 1. statisches Typsystem 2. Garbage Collection 3. keine Vererbung 4. Concurrency eingebaut 5. native Ausführung Linux, Win, z/OS, 386, amd64, ARM, wasm, ...
  • 7. Go Proverbs 18 Prinzipien zurGo Entwicklung # von Rob Pike 2015 vorgestellt # "Clearis betterthan clever." #
  • 8. CLI Proverbs ohne Argumente > pro Clear is better than clever.
  • 9. CLI Projekt aufsetzen // 1. Go Modul erstellen (erzeugt go.mod) > go mod init crossnative.com/pro // 2. Datei main.go erstellen package main import "fmt" func main() { fmt.Println("Hello Go Pro!") } Ausführen go build . // 1. Code kompilieren ./pro // 2. Binary ausführen go run . // Code kompilieren und ausführen
  • 12.
  • 13. Proverbs Modul nutzen // 1. Proverbs Modul Dependency > go get github.com/jboursiquot/go-proverbs // 2. Go Modul Descriptor go.mod module crossnative.com/pro go 1.22 require github.com/jboursiquot/go-proverbs v0.0.2
  • 14. Zufälliges Proverb ausgeben import ( "github.com/jboursiquot/go-proverbs" ) package main 1 2 3 "fmt" 4 5 6 7 func main() { 8 fmt.Println(proverbs.Random()) 9 } 10 import ( "github.com/jboursiquot/go-proverbs" ) fmt.Println(proverbs.Random()) package main 1 2 3 "fmt" 4 5 6 7 func main() { 8 9 } 10 package main import ( "fmt" "github.com/jboursiquot/go-proverbs" ) func main() { fmt.Println(proverbs.Random()) } 1 2 3 4 5 6 7 8 9 10 // Ausgabe `go run .` &{Make the zero value useful. http://youtube.com/322}
  • 15. 💡Structs und Pointer // Pointer Variable auf Proverb Struct var p *proverbs.Proverb = proverbs.Random() package main 1 2 import ( 3 "fmt" 4 "github.com/jboursiquot/go-proverbs" 5 ) 6 7 func main() { 8 9 10 11 fmt.Println(p) 12 } 13 package main import ( "fmt" "github.com/jboursiquot/go-proverbs" ) func main() { // Pointer Variable auf Proverb Struct var p *proverbs.Proverb = proverbs.Random() fmt.Println(p) } 1 2 3 4 5 6 7 8 9 10 11 12 13 // Struct statt Klasse type Proverb struct { Saying string Link string } 1 2 3 4 5
  • 16. Zufälliges Proverb ausgeben import ( "github.com/jboursiquot/go-proverbs" ) package main 1 2 3 "fmt" 4 5 6 7 func main() { 8 var p *proverbs.Proverb = proverbs.Random() 9 10 // Zugriff auf Property des Structs 11 fmt.Println(p.Saying) 12 } 13 import ( "github.com/jboursiquot/go-proverbs" ) var p *proverbs.Proverb = proverbs.Random() package main 1 2 3 "fmt" 4 5 6 7 func main() { 8 9 10 // Zugriff auf Property des Structs 11 fmt.Println(p.Saying) 12 } 13 // Zugriff auf Property des Structs fmt.Println(p.Saying) package main 1 2 import ( 3 "fmt" 4 "github.com/jboursiquot/go-proverbs" 5 ) 6 7 func main() { 8 var p *proverbs.Proverb = proverbs.Random() 9 10 11 12 } 13 package main import ( "fmt" "github.com/jboursiquot/go-proverbs" ) func main() { var p *proverbs.Proverb = proverbs.Random() // Zugriff auf Property des Structs fmt.Println(p.Saying) } 1 2 3 4 5 6 7 8 9 10 11 12 13 // Ausgabe `go run .` Make the zero value useful.
  • 17. CLI Proverbs mit Count > pro -count=3 Clear is better than clever. Documentation is for users. Don't panic.
  • 18. Flag fürCount "flag" // 1. Flags definieren var count *int = flag.Int("count", 1, "proverb count") import ( 1 2 "fmt" 3 "github.com/jboursiquot/go-proverbs" 4 ) 5 6 func main() { 7 8 9 10 // 2. Flags parsen 11 flag.Parse() 12 13 // 3. Ausgabe in Schleife 14 for i := 0; i < *count; i++ { 15 var p *proverbs.Proverb = proverbs.Random() 16 fmt.Println(p.Saying) 17 } 18 } 19 // 2. Flags parsen flag.Parse() import ( 1 "flag" 2 "fmt" 3 "github.com/jboursiquot/go-proverbs" 4 ) 5 6 func main() { 7 // 1. Flags definieren 8 var count *int = flag.Int("count", 1, "proverb count") 9 10 11 12 13 // 3. Ausgabe in Schleife 14 for i := 0; i < *count; i++ { 15 var p *proverbs.Proverb = proverbs.Random() 16 fmt.Println(p.Saying) 17 } 18 } 19 // 3. Ausgabe in Schleife for i := 0; i < *count; i++ { var p *proverbs.Proverb = proverbs.Random() fmt.Println(p.Saying) } import ( 1 "flag" 2 "fmt" 3 "github.com/jboursiquot/go-proverbs" 4 ) 5 6 func main() { 7 // 1. Flags definieren 8 var count *int = flag.Int("count", 1, "proverb count") 9 10 // 2. Flags parsen 11 flag.Parse() 12 13 14 15 16 17 18 } 19 import ( "flag" "fmt" "github.com/jboursiquot/go-proverbs" ) func main() { // 1. Flags definieren var count *int = flag.Int("count", 1, "proverb count") // 2. Flags parsen flag.Parse() // 3. Ausgabe in Schleife for i := 0; i < *count; i++ { var p *proverbs.Proverb = proverbs.Random() fmt.Println(p.Saying) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // Compile mit `go build .`, Ausgabe mit `pro -count=2` Make the zero value useful. Reflection is never clear.
  • 19. CLI Proverbs mit ungültigem Count > pro -count= flag needs an argument: -count Usage of ./pro: -count int proverb count (default 1)
  • 20. Flag fürCount Refactored count := flag.Int("count", 1, "proverb count") p := proverbs.Random() import ( 1 "flag" 2 "fmt" 3 "github.com/jboursiquot/go-proverbs" 4 ) 5 6 func main() { 7 // 1. Flags definieren 8 9 10 // 2. Flags parsen 11 flag.Parse() 12 13 // 3. Ausgabe in Schleife 14 for range *count { 15 16 fmt.Println(p.Saying) 17 } 18 } 19 for range *count { } import ( 1 "flag" 2 "fmt" 3 "github.com/jboursiquot/go-proverbs" 4 ) 5 6 func main() { 7 // 1. Flags definieren 8 count := flag.Int("count", 1, "proverb count") 9 10 // 2. Flags parsen 11 flag.Parse() 12 13 // 3. Ausgabe in Schleife 14 15 p := proverbs.Random() 16 fmt.Println(p.Saying) 17 18 } 19 import ( "flag" "fmt" "github.com/jboursiquot/go-proverbs" ) func main() { // 1. Flags definieren count := flag.Int("count", 1, "proverb count") // 2. Flags parsen flag.Parse() // 3. Ausgabe in Schleife for range *count { p := proverbs.Random() fmt.Println(p.Saying) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // Compile mit `go build .`, Ausgabe mit `pro -count=2` Make the zero value useful. Reflection is never clear.
  • 22. File Downloader ParallelerFile Download # Nutzt Goroutinen und Channels # Context is King #
  • 23. File Downloader1/3 func main() { urls := []string{ "https://go.dev/dl/go1.22.2.src.tar.gz", "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", } } 1 2 3 4 5 6 // URL Download 7 ctx := context.Background() 8 downloadURLs(ctx, urls) 9 10 11 func downloadURLs(ctx context.Context, urls []string) { 12 // ... 13 } 14 func main() { urls := []string{ "https://go.dev/dl/go1.22.2.src.tar.gz", "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", } } 1 2 3 4 5 6 // URL Download 7 ctx := context.Background() 8 downloadURLs(ctx, urls) 9 10 11 func downloadURLs(ctx context.Context, urls []string) { 12 // ... 13 } 14 func main() { // URL Download ctx := context.Background() downloadURLs(ctx, urls) } 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 7 8 9 10 11 func downloadURLs(ctx context.Context, urls []string) { 12 // ... 13 } 14 func main() { urls := []string{ "https://go.dev/dl/go1.22.2.src.tar.gz", "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", } // URL Download ctx := context.Background() downloadURLs(ctx, urls) } func downloadURLs(ctx context.Context, urls []string) { // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  • 24. File Downloader2/3 // 1. Channel für Download Jobs jobs := make(chan int, len(urls)) func downloadURLs(ctx context.Context, urls []string) { 1 2 3 4 // 2. Go Routinen für Downloads starten 5 for _, url := range urls { 6 go func() { 7 downloadURL(ctx, url) 8 jobs <- 1 // Send an Channel (blockiert) 9 }() 10 } 11 12 // 3. Warten auf Ende aller Go Routinen 13 for range len(urls) { 14 <-jobs // Receive von Channel (blockiert) 15 } 16 } 17 // 2. Go Routinen für Downloads starten for _, url := range urls { go func() { downloadURL(ctx, url) jobs <- 1 // Send an Channel (blockiert) }() } func downloadURLs(ctx context.Context, urls []string) { 1 // 1. Channel für Download Jobs 2 jobs := make(chan int, len(urls)) 3 4 5 6 7 8 9 10 11 12 // 3. Warten auf Ende aller Go Routinen 13 for range len(urls) { 14 <-jobs // Receive von Channel (blockiert) 15 } 16 } 17 // 3. Warten auf Ende aller Go Routinen for range len(urls) { <-jobs // Receive von Channel (blockiert) } func downloadURLs(ctx context.Context, urls []string) { 1 // 1. Channel für Download Jobs 2 jobs := make(chan int, len(urls)) 3 4 // 2. Go Routinen für Downloads starten 5 for _, url := range urls { 6 go func() { 7 downloadURL(ctx, url) 8 jobs <- 1 // Send an Channel (blockiert) 9 }() 10 } 11 12 13 14 15 16 } 17 func downloadURLs(ctx context.Context, urls []string) { // 1. Channel für Download Jobs jobs := make(chan int, len(urls)) // 2. Go Routinen für Downloads starten for _, url := range urls { go func() { downloadURL(ctx, url) jobs <- 1 // Send an Channel (blockiert) }() } // 3. Warten auf Ende aller Go Routinen for range len(urls) { <-jobs // Receive von Channel (blockiert) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  • 25. File Downloader3/3 func downloadURL(ctx context.Context, url string) { // 1. HTTP Request mit Context erstellen req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 1 2 3 4 // 2. HTTP Aufruf durchführen 5 httpClient := http.Client{} 6 resp, _ := httpClient.Do(req) 7 defer resp.Body.Close() 8 9 // 3. Ausgabe in Datei 10 file, _ := os.Create(filepath.Base(url)) 11 defer file.Close() 12 13 // 4. HTTP Body in Datei streamen 14 io.Copy(file, resp.Body) 15 } 16 // 2. HTTP Aufruf durchführen httpClient := http.Client{} resp, _ := httpClient.Do(req) defer resp.Body.Close() func downloadURL(ctx context.Context, url string) { 1 // 1. HTTP Request mit Context erstellen 2 req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 3 4 5 6 7 8 9 // 3. Ausgabe in Datei 10 file, _ := os.Create(filepath.Base(url)) 11 defer file.Close() 12 13 // 4. HTTP Body in Datei streamen 14 io.Copy(file, resp.Body) 15 } 16 // 3. Ausgabe in Datei file, _ := os.Create(filepath.Base(url)) defer file.Close() func downloadURL(ctx context.Context, url string) { 1 // 1. HTTP Request mit Context erstellen 2 req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 3 4 // 2. HTTP Aufruf durchführen 5 httpClient := http.Client{} 6 resp, _ := httpClient.Do(req) 7 defer resp.Body.Close() 8 9 10 11 12 13 // 4. HTTP Body in Datei streamen 14 io.Copy(file, resp.Body) 15 } 16 // 4. HTTP Body in Datei streamen io.Copy(file, resp.Body) func downloadURL(ctx context.Context, url string) { 1 // 1. HTTP Request mit Context erstellen 2 req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 3 4 // 2. HTTP Aufruf durchführen 5 httpClient := http.Client{} 6 resp, _ := httpClient.Do(req) 7 defer resp.Body.Close() 8 9 // 3. Ausgabe in Datei 10 file, _ := os.Create(filepath.Base(url)) 11 defer file.Close() 12 13 14 15 } 16 func downloadURL(ctx context.Context, url string) { // 1. HTTP Request mit Context erstellen req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) // 2. HTTP Aufruf durchführen httpClient := http.Client{} resp, _ := httpClient.Do(req) defer resp.Body.Close() // 3. Ausgabe in Datei file, _ := os.Create(filepath.Base(url)) defer file.Close() // 4. HTTP Body in Datei streamen io.Copy(file, resp.Body) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 26. File Downloader3/3 mit Fehlern func downloadURL(ctx context.Context, url string) error { } 1 // 1. HTTP Request mit Context erstellen 2 req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 3 if err != nil { 4 return err 5 } 6 7 // 2. HTTP Aufruf durchführen 8 // ... 9 10 // 1. HTTP Request mit Context erstellen req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return err } func downloadURL(ctx context.Context, url string) error { 1 2 3 4 5 6 7 // 2. HTTP Aufruf durchführen 8 // ... 9 } 10 func downloadURL(ctx context.Context, url string) error { // 1. HTTP Request mit Context erstellen req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return err } // 2. HTTP Aufruf durchführen // ... } 1 2 3 4 5 6 7 8 9 10
  • 27. File Downloadermit Timeout // 1. Context mit Cancel Func ctx, cancel := context.WithCancel(context.Background()) // 3. URL Download downloadURLs(ctx, urls) func main() { 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 7 8 9 // 2. Timer Channel nutzen 10 timer := time.After(3 * time.Second) 11 go func() { 12 <-timer // Receive timer Channel 13 log.Println("Canceled due to timeout") 14 cancel() 15 }() 16 17 18 19 } 20 // 2. Timer Channel nutzen timer := time.After(3 * time.Second) go func() { <-timer // Receive timer Channel log.Println("Canceled due to timeout") cancel() }() func main() { 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 // 1. Context mit Cancel Func 7 ctx, cancel := context.WithCancel(context.Background()) 8 9 10 11 12 13 14 15 16 17 // 3. URL Download 18 downloadURLs(ctx, urls) 19 } 20 // 1. Context mit Cancel Func ctx, cancel := context.WithCancel(context.Background()) // 2. Timer Channel nutzen timer := time.After(3 * time.Second) go func() { <-timer // Receive timer Channel log.Println("Canceled due to timeout") cancel() }() // 3. URL Download downloadURLs(ctx, urls) func main() { 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 } 20
  • 28. File Downloadermit Interrupt // 1. Context mit Cancel Func ctx, cancel := context.WithCancel(context.Background()) // 3. URL Download downloadURLs(ctx, urls) func main() { 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 7 8 9 // 2. Interrupt Channel nutzen 10 interrupt := make(chan os.Signal, 1) 11 signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) 12 go func() { 13 <-interrupt // Receive interrupt Channel 14 log.Println("Canceled due to interrupt") 15 cancel() 16 }() 17 18 19 20 } 21 // 2. Interrupt Channel nutzen interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) go func() { <-interrupt // Receive interrupt Channel log.Println("Canceled due to interrupt") cancel() }() func main() { 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 // 1. Context mit Cancel Func 7 ctx, cancel := context.WithCancel(context.Background()) 8 9 10 11 12 13 14 15 16 17 18 // 3. URL Download 19 downloadURLs(ctx, urls) 20 } 21 // 1. Context mit Cancel Func ctx, cancel := context.WithCancel(context.Background()) // 2. Interrupt Channel nutzen interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) go func() { <-interrupt // Receive interrupt Channel log.Println("Canceled due to interrupt") cancel() }() // 3. URL Download downloadURLs(ctx, urls) func main() { 1 urls := []string{ 2 "https://go.dev/dl/go1.22.2.src.tar.gz", 3 "https://go.dev/dl/go1.22.2.darwin-amd64.tar.gz", 4 } 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 } 21
  • 29. File Downloadermit Select // 1. Context mit Cancel Func // + Timeout Channel // + Interrupt Channel func main() { 1 2 3 4 5 go func() { 6 select { 7 // 2a. Receive timer Channel 8 case <-timer: 9 log.Println("Canceled due to timeout") 10 cancel() 11 // 2b. Receive interrupt Channel 12 case <-interrupt: 13 log.Println("Canceled due to interrupt") 14 cancel() 15 } 16 }() 17 18 // 3. URL Download 19 downloadURLs(ctx, urls) 20 } 21 select { // 2a. Receive timer Channel case <-timer: log.Println("Canceled due to timeout") cancel() } func main() { 1 // 1. Context mit Cancel Func 2 // + Timeout Channel 3 // + Interrupt Channel 4 5 go func() { 6 7 8 9 10 11 // 2b. Receive interrupt Channel 12 case <-interrupt: 13 log.Println("Canceled due to interrupt") 14 cancel() 15 16 }() 17 18 // 3. URL Download 19 downloadURLs(ctx, urls) 20 } 21 select { // 2b. Receive interrupt Channel case <-interrupt: log.Println("Canceled due to interrupt") cancel() } func main() { 1 // 1. Context mit Cancel Func 2 // + Timeout Channel 3 // + Interrupt Channel 4 5 go func() { 6 7 // 2a. Receive timer Channel 8 case <-timer: 9 log.Println("Canceled due to timeout") 10 cancel() 11 12 13 14 15 16 }() 17 18 // 3. URL Download 19 downloadURLs(ctx, urls) 20 } 21 select { // 2a. Receive timer Channel case <-timer: log.Println("Canceled due to timeout") cancel() // 2b. Receive interrupt Channel case <-interrupt: log.Println("Canceled due to interrupt") cancel() } func main() { 1 // 1. Context mit Cancel Func 2 // + Timeout Channel 3 // + Interrupt Channel 4 5 go func() { 6 7 8 9 10 11 12 13 14 15 16 }() 17 18 // 3. URL Download 19 downloadURLs(ctx, urls) 20 } 21
  • 30. 🖥️CLI Tools Standardlib Flags # einfache Releases mit Goreleaser # Cobra CLI Lib wenn's komplexerwird # Github, Kubernetes sind Go CLIs #
  • 32. Set up Cats App # 1. Verzeichnis erstellen mkdir cats cd cats # 2. Go Modul aufsetzen go mod init crossnative.com/cats # 3. Go Datei erstellen touch main.go
  • 33. Cat API simple func main() { http.HandleFunc("GET /api/cats", catAPIHandler) http.ListenAndServe(":8080", nil) } func catAPIHandler(w http.ResponseWriter, r *http.Request) { 1 fmt.Fprintf(w, "Meow!") 2 w.WriteHeader(http.StatusOK) 3 } 4 5 6 7 8 9 func catAPIHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Meow!") w.WriteHeader(http.StatusOK) } 1 2 3 4 5 func main() { 6 http.HandleFunc("GET /api/cats", catAPIHandler) 7 http.ListenAndServe(":8080", nil) 8 } 9
  • 34. Cat API mit JSON // 1. Struct mit JSON Tag definieren type Cat struct { Name string `json:"name"` } 1 2 3 4 5 func catAPIHandler(w http.ResponseWriter, r *http.Request) { 6 // 2. Slice erstellen 7 cats := make([]Cat, 1) 8 9 // 3. Struct erstellen und einfügen 10 cats[0] = Cat{Name: "Ginger"} 11 12 // 4. JSON rendern 13 json.NewEncoder(w).Encode(cats) 14 } 15 16 func main() { 17 http.HandleFunc("GET /api/cats", catAPIHandler) 18 http.ListenAndServe(":8080", nil) 19 } 20 func catAPIHandler(w http.ResponseWriter, r *http.Request) { } // 1. Struct mit JSON Tag definieren 1 type Cat struct { 2 Name string `json:"name"` 3 } 4 5 6 // 2. Slice erstellen 7 cats := make([]Cat, 1) 8 9 // 3. Struct erstellen und einfügen 10 cats[0] = Cat{Name: "Ginger"} 11 12 // 4. JSON rendern 13 json.NewEncoder(w).Encode(cats) 14 15 16 func main() { 17 http.HandleFunc("GET /api/cats", catAPIHandler) 18 http.ListenAndServe(":8080", nil) 19 } 20 func catAPIHandler(w http.ResponseWriter, r *http.Request) { // 2. Slice erstellen cats := make([]Cat, 1) } // 1. Struct mit JSON Tag definieren 1 type Cat struct { 2 Name string `json:"name"` 3 } 4 5 6 7 8 9 // 3. Struct erstellen und einfügen 10 cats[0] = Cat{Name: "Ginger"} 11 12 // 4. JSON rendern 13 json.NewEncoder(w).Encode(cats) 14 15 16 func main() { 17 http.HandleFunc("GET /api/cats", catAPIHandler) 18 http.ListenAndServe(":8080", nil) 19 } 20 func catAPIHandler(w http.ResponseWriter, r *http.Request) { // 3. Struct erstellen und einfügen cats[0] = Cat{Name: "Ginger"} } // 1. Struct mit JSON Tag definieren 1 type Cat struct { 2 Name string `json:"name"` 3 } 4 5 6 // 2. Slice erstellen 7 cats := make([]Cat, 1) 8 9 10 11 12 // 4. JSON rendern 13 json.NewEncoder(w).Encode(cats) 14 15 16 func main() { 17 http.HandleFunc("GET /api/cats", catAPIHandler) 18 http.ListenAndServe(":8080", nil) 19 } 20 func catAPIHandler(w http.ResponseWriter, r *http.Request) { // 4. JSON rendern json.NewEncoder(w).Encode(cats) } // 1. Struct mit JSON Tag definieren 1 type Cat struct { 2 Name string `json:"name"` 3 } 4 5 6 // 2. Slice erstellen 7 cats := make([]Cat, 1) 8 9 // 3. Struct erstellen und einfügen 10 cats[0] = Cat{Name: "Ginger"} 11 12 13 14 15 16 func main() { 17 http.HandleFunc("GET /api/cats", catAPIHandler) 18 http.ListenAndServe(":8080", nil) 19 } 20 // 1. Struct mit JSON Tag definieren type Cat struct { Name string `json:"name"` } func catAPIHandler(w http.ResponseWriter, r *http.Request) { // 2. Slice erstellen cats := make([]Cat, 1) // 3. Struct erstellen und einfügen cats[0] = Cat{Name: "Ginger"} // 4. JSON rendern json.NewEncoder(w).Encode(cats) } func main() { http.HandleFunc("GET /api/cats", catAPIHandler) http.ListenAndServe(":8080", nil) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  • 35. Cat API mit JSON # Query cat API curl -s http://localhost:8080/api/cats | jq 1 2 [ 3 { 4 "name": "Ginger" 5 } 6 ] 7 [ { "name": "Ginger" } ] # Query cat API 1 curl -s http://localhost:8080/api/cats | jq 2 3 4 5 6 7
  • 36. Test Cat API cat_api_test.go func TestCatAPIHandler(t *testing.T) { } 1 // 1. Test Request erstellen 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 // 2. HTTP Recorder erstellen (ist http.ResponseWriter) 5 rec := httptest.NewRecorder() 6 7 // 3. Handler aufrufen 8 catAPIHandler(rec, req) 9 10 // 4. Response prüfen 11 if rec.Code != http.StatusOK { 12 t.Errorf("got status %v expected %v", rec.Code, http.StatusOK) 13 } 14 15 // 1. Test Request erstellen req, _ := http.NewRequest("GET", "/api/cats", nil) func TestCatAPIHandler(t *testing.T) { 1 2 3 4 // 2. HTTP Recorder erstellen (ist http.ResponseWriter) 5 rec := httptest.NewRecorder() 6 7 // 3. Handler aufrufen 8 catAPIHandler(rec, req) 9 10 // 4. Response prüfen 11 if rec.Code != http.StatusOK { 12 t.Errorf("got status %v expected %v", rec.Code, http.StatusOK) 13 } 14 } 15 // 2. HTTP Recorder erstellen (ist http.ResponseWriter) rec := httptest.NewRecorder() func TestCatAPIHandler(t *testing.T) { 1 // 1. Test Request erstellen 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 5 6 7 // 3. Handler aufrufen 8 catAPIHandler(rec, req) 9 10 // 4. Response prüfen 11 if rec.Code != http.StatusOK { 12 t.Errorf("got status %v expected %v", rec.Code, http.StatusOK) 13 } 14 } 15 // 3. Handler aufrufen catAPIHandler(rec, req) func TestCatAPIHandler(t *testing.T) { 1 // 1. Test Request erstellen 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 // 2. HTTP Recorder erstellen (ist http.ResponseWriter) 5 rec := httptest.NewRecorder() 6 7 8 9 10 // 4. Response prüfen 11 if rec.Code != http.StatusOK { 12 t.Errorf("got status %v expected %v", rec.Code, http.StatusOK) 13 } 14 } 15 // 4. Response prüfen if rec.Code != http.StatusOK { t.Errorf("got status %v expected %v", rec.Code, http.StatusOK) } func TestCatAPIHandler(t *testing.T) { 1 // 1. Test Request erstellen 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 // 2. HTTP Recorder erstellen (ist http.ResponseWriter) 5 rec := httptest.NewRecorder() 6 7 // 3. Handler aufrufen 8 catAPIHandler(rec, req) 9 10 11 12 13 14 } 15 func TestCatAPIHandler(t *testing.T) { // 1. Test Request erstellen req, _ := http.NewRequest("GET", "/api/cats", nil) // 2. HTTP Recorder erstellen (ist http.ResponseWriter) rec := httptest.NewRecorder() // 3. Handler aufrufen catAPIHandler(rec, req) // 4. Response prüfen if rec.Code != http.StatusOK { t.Errorf("got status %v expected %v", rec.Code, http.StatusOK) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  • 37. Test ausführen go test -v ./... 1 === RUN TestCatAPIHandler 2 --- PASS: TestCatAPIHandler (0.00s) 3 PASS 4 coverage: 50.0% of statements 5 ok crossnative.com/cats 0.127s coverage: 50.0% of statements 6 === RUN TestCatAPIHandler --- PASS: TestCatAPIHandler (0.00s) PASS coverage: 50.0% of statements ok crossnative.com/cats 0.127s coverage: 50.0% of statements go test -v ./... 1 2 3 4 5 6
  • 39. Cats Web App // 1. Mulitplexer erzeugen mux := http.NewServeMux() func indexHandler(w http.ResponseWriter, r *http.Request) { 1 tpl := template.Must(template.ParseFiles("index.html")) 2 tpl.Execute(w, nil) 3 } 4 5 func main() { 6 7 8 9 // 2. Handler registrieren 10 mux.HandleFunc("/", indexHandler) 11 12 // 3. Server mit Mulitplexer starten 13 http.ListenAndServe(":8080", mux) 14 } 15 // 2. Handler registrieren mux.HandleFunc("/", indexHandler) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 tpl := template.Must(template.ParseFiles("index.html")) 2 tpl.Execute(w, nil) 3 } 4 5 func main() { 6 // 1. Mulitplexer erzeugen 7 mux := http.NewServeMux() 8 9 10 11 12 // 3. Server mit Mulitplexer starten 13 http.ListenAndServe(":8080", mux) 14 } 15 // 3. Server mit Mulitplexer starten http.ListenAndServe(":8080", mux) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 tpl := template.Must(template.ParseFiles("index.html")) 2 tpl.Execute(w, nil) 3 } 4 5 func main() { 6 // 1. Mulitplexer erzeugen 7 mux := http.NewServeMux() 8 9 // 2. Handler registrieren 10 mux.HandleFunc("/", indexHandler) 11 12 13 14 } 15 func indexHandler(w http.ResponseWriter, r *http.Request) { tpl := template.Must(template.ParseFiles("index.html")) tpl.Execute(w, nil) } func main() { // 1. Mulitplexer erzeugen mux := http.NewServeMux() // 2. Handler registrieren mux.HandleFunc("/", indexHandler) // 3. Server mit Mulitplexer starten http.ListenAndServe(":8080", mux) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  • 40. File Serveraus Binary //go:embed assets var assets embed.FS // Serve Files mux.Handle("/assets/", http.FileServer(http.FS(assets))) 1 2 3 func main() { 4 mux := http.NewServeMux() 5 mux.HandleFunc("/", indexHandler) 6 7 8 9 10 http.ListenAndServe(":8080", mux) 11 } 12
  • 41. Index HandlerTemplate mit Daten type Cat struct { Name string } func indexHandler(w ResponseWriter, r *Request) { // 1. Slice erstellen cat := make([]Cat, 1) // 2. Struct erstellen und einfügen cat[0] = Cat{Name: "Ginger"} // 3. Template rendern tpl := template.Must(template.ParseFiles("index.html")) tpl.Execute(w, cat) } <body> <h1>Cats App</h1> {{ range . }} <h2>{{ .Name }}</h2> {{ end }} </body>
  • 42.
  • 43. Index Handlermit Cats API Query Cats API GET https://api.thecatapi.com/v1/breeds?limit=5 [ { "id": "abys", "name": "Abyssinian", "image": { "url": "https://cdn2.thecatapi.com/0XYvRd7oD.jpg" } }, { "id": "aege", "name": "Aegean", "image": { "url": "https://cdn2.thecatapi.com/ozEvzdVM-.jpg" } }, ... ] Map JSON auf Struct type Cat struct { ID string `json:"id"` Name string `json:"name"` Image struct { URL string `json:"url"` } `json:"image"` }
  • 44. Index Handlermit Cats API // 1. Cat API Aufruf (Fehler ignorieren) resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") func indexHandler(w http.ResponseWriter, r *http.Request) { 1 2 3 4 // 2. Slice für Cat Structs 5 cat := make([]Cat, 5) 6 7 // 3. Response Body parsen 8 defer resp.Body.Close() 9 body, _ := ioutil.ReadAll(resp.Body) 10 json.Unmarshal(body, &cat) 11 12 // 4. Template rendern 13 tpl.Execute(w, cat) 14 } 15 // 2. Slice für Cat Structs cat := make([]Cat, 5) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 // 1. Cat API Aufruf (Fehler ignorieren) 2 resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") 3 4 5 6 7 // 3. Response Body parsen 8 defer resp.Body.Close() 9 body, _ := ioutil.ReadAll(resp.Body) 10 json.Unmarshal(body, &cat) 11 12 // 4. Template rendern 13 tpl.Execute(w, cat) 14 } 15 // 3. Response Body parsen defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) json.Unmarshal(body, &cat) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 // 1. Cat API Aufruf (Fehler ignorieren) 2 resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") 3 4 // 2. Slice für Cat Structs 5 cat := make([]Cat, 5) 6 7 8 9 10 11 12 // 4. Template rendern 13 tpl.Execute(w, cat) 14 } 15 // 4. Template rendern tpl.Execute(w, cat) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 // 1. Cat API Aufruf (Fehler ignorieren) 2 resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") 3 4 // 2. Slice für Cat Structs 5 cat := make([]Cat, 5) 6 7 // 3. Response Body parsen 8 defer resp.Body.Close() 9 body, _ := ioutil.ReadAll(resp.Body) 10 json.Unmarshal(body, &cat) 11 12 13 14 } 15 func indexHandler(w http.ResponseWriter, r *http.Request) { // 1. Cat API Aufruf (Fehler ignorieren) resp, _ := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") // 2. Slice für Cat Structs cat := make([]Cat, 5) // 3. Response Body parsen defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) json.Unmarshal(body, &cat) // 4. Template rendern tpl.Execute(w, cat) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  • 45. Index Handlermit Fehlerhandling 💣 // 1. Cat API Aufruf resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") func indexHandler(w http.ResponseWriter, r *http.Request) { 1 2 3 // Fehler behandeln 4 if err != nil { 5 http.Error(w, "Cats API error", http.StatusInternalServerError) 6 return 7 } 8 9 // 2. Slice für Cat Structs 10 cat := make([]Cat, 5) 11 12 // 3. Response Body parsen 13 defer resp.Body.Close() 14 body, _ := ioutil.ReadAll(resp.Body) 15 err := json.Unmarshal(body, &cat) 16 // TODO: Fehler behandeln 17 18 // 4. Template rendern 19 err := tpl.Execute(w, cat) 20 // TODO: Fehler behandeln 21 } 22 // Fehler behandeln if err != nil { http.Error(w, "Cats API error", http.StatusInternalServerError) return } func indexHandler(w http.ResponseWriter, r *http.Request) { 1 // 1. Cat API Aufruf 2 resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") 3 4 5 6 7 8 9 // 2. Slice für Cat Structs 10 cat := make([]Cat, 5) 11 12 // 3. Response Body parsen 13 defer resp.Body.Close() 14 body, _ := ioutil.ReadAll(resp.Body) 15 err := json.Unmarshal(body, &cat) 16 // TODO: Fehler behandeln 17 18 // 4. Template rendern 19 err := tpl.Execute(w, cat) 20 // TODO: Fehler behandeln 21 } 22 // 1. Cat API Aufruf resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") // Fehler behandeln if err != nil { http.Error(w, "Cats API error", http.StatusInternalServerError) return } err := json.Unmarshal(body, &cat) // TODO: Fehler behandeln err := tpl.Execute(w, cat) // TODO: Fehler behandeln func indexHandler(w http.ResponseWriter, r *http.Request) { 1 2 3 4 5 6 7 8 9 // 2. Slice für Cat Structs 10 cat := make([]Cat, 5) 11 12 // 3. Response Body parsen 13 defer resp.Body.Close() 14 body, _ := ioutil.ReadAll(resp.Body) 15 16 17 18 // 4. Template rendern 19 20 21 } 22
  • 46. 🌐Web App Standardlib JSON und Router # HTTPTests # Querschnittsfeatures durch Middleware #
  • 48. λ Lambda Function Go ideal fürServerless Functions # schnellerStart, geringerSpeicherbedarf # unterstützt von AWS, Azure, Google #
  • 50. λ Lambda Function // 1. Lambda Go Projekt aufsetzen > sam init 1 2 3 // 2. Lambda bauen 4 > sam build 5 6 // 3. Lambda ausführen 7 > sam local invoke -e events/event.json 8 Invoking bootstrap (provided.al2023) 9 Local image is up-to-date 10 Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64. 11 12 Mounting .aws-sam/build/HelloWorldFunction, inside runtime container 13 REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms 14 Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB 15 {"statusCode": 200, "body": "Hello JAX!"} 16 // 2. Lambda bauen > sam build // 1. Lambda Go Projekt aufsetzen 1 > sam init 2 3 4 5 6 // 3. Lambda ausführen 7 > sam local invoke -e events/event.json 8 Invoking bootstrap (provided.al2023) 9 Local image is up-to-date 10 Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64. 11 12 Mounting .aws-sam/build/HelloWorldFunction, inside runtime container 13 REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms 14 Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB 15 {"statusCode": 200, "body": "Hello JAX!"} 16 // 3. Lambda ausführen > sam local invoke -e events/event.json Invoking bootstrap (provided.al2023) Local image is up-to-date Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64. Mounting .aws-sam/build/HelloWorldFunction, inside runtime container REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB {"statusCode": 200, "body": "Hello JAX!"} // 1. Lambda Go Projekt aufsetzen 1 > sam init 2 3 // 2. Lambda bauen 4 > sam build 5 6 7 8 9 10 11 12 13 14 15 16 // 1. Lambda Go Projekt aufsetzen > sam init // 2. Lambda bauen > sam build // 3. Lambda ausführen > sam local invoke -e events/event.json Invoking bootstrap (provided.al2023) Local image is up-to-date Using local image: public.ecr.aws/lambda/provided:al2023-rapid-x86_64. Mounting .aws-sam/build/HelloWorldFunction, inside runtime container REPORT RequestId: 37876f36 Init Duration: 0.52 ms Duration: 80.04 ms Billed Duration: 81 ms Memory Size: 128 MB Max Memory Used: 128 MB {"statusCode": 200, "body": "Hello JAX!"} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 52. λ Lambda Function # Query AWS Lambda curl -s https://0up9.eu-north-1.amazonaws.com/Prod/hello 1 2 Hello JAX! 3 Hello JAX! # Query AWS Lambda 1 curl -s https://0up9.eu-north-1.amazonaws.com/Prod/hello 2 3 Footprint Package Size 5,3 MB Billed Duration 70 ms Max Memory Used 18 MB Init Duration 63.66 ms # # # #
  • 53. λ Lambda Function func main() { lambda.Start(handler) } import ( 1 "fmt" 2 "github.com/aws/aws-lambda-go/events" 3 "github.com/aws/aws-lambda-go/lambda" 4 ) 5 6 func handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) 7 return events.APIGatewayProxyResponse{ 8 Body: "Hello JAX!", 9 StatusCode: 200, 10 }, nil 11 } 12 13 14 15 16 func handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) return events.APIGatewayProxyResponse{ Body: "Hello JAX!", StatusCode: 200, }, nil } import ( 1 "fmt" 2 "github.com/aws/aws-lambda-go/events" 3 "github.com/aws/aws-lambda-go/lambda" 4 ) 5 6 7 8 9 10 11 12 13 func main() { 14 lambda.Start(handler) 15 } 16 import ( "fmt" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) return events.APIGatewayProxyResponse{ Body: "Hello JAX!", StatusCode: 200, }, nil } func main() { lambda.Start(handler) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 54. λ Lambda Function Projekt |-events | event.json // Beispiel Request |-hello-world // Go App | go.mod | go.sum | main.go | main_test.go | Makefile // Build File | samconfig.toml // SAM Config | template.yaml // SAM Config | README.md
  • 55. 🖥️CLI Tools Projekt Setup Variablen, Schleifen Goroutinen, Channels Context Structs # # # # # 🌐Web App Web Server Slice Unit Test JSON Fehlerhandling # # # # # λ Lambda Func AWS Setup Serverless Experience # #
  • 56. 3 Gründe fürGo 1. Einfach 2. Mächtig 3. Langweilig
  • 57. Go liebt Microservices Serverless Functions Kommandozeilen-Tools DevOps und Cloud
  • 58.