SlideShare ist ein Scribd-Unternehmen logo
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

Weitere ähnliche Inhalte

Ähnlich wie 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 Go
Frank 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 Vagrant
B1 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_script
Manfred Steyer
 
Tech Talk: Groovy
Tech Talk: GroovyTech Talk: Groovy
Tech Talk: Groovy
mwie
 
Versionskontrolle mit Git
Versionskontrolle mit GitVersionskontrolle mit Git
Versionskontrolle mit Git
NETUserGroupBern
 
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
 
Grunt
GruntGrunt
Grunt
nikflip
 
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
NETWAYS
 
Bottle - Python Web Microframework
Bottle - Python Web MicroframeworkBottle - Python Web Microframework
Bottle - Python Web Microframework
Markus Zapke-Gründemann
 
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
Jan 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 bauen
Schlomo Schapiro
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in Go
Frank Müller
 
Ein Gopher im Netz
Ein Gopher im NetzEin Gopher im Netz
Ein Gopher im Netz
Frank 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 morgen
Dr. 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 Lange
NETWAYS
 
Check cisco voice
Check cisco voiceCheck cisco voice
Check cisco voice
bboguhn
 
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
 

Ähnlich wie 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
 

Mehr von 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 Cloud
Jan 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. Java
Jan 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 101
Jan 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 Ökosystem
Jan Stamer
 
JCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web AppsJCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web Apps
Jan Stamer
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101
Jan 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-Entwickler
Jan 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 Apps
Jan 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
 

Mehr von 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.