SlideShare a Scribd company logo
1 of 38
Download to read offline
GO WEB
DEVELOPMENT 101
3 MONTHS to be productive
74% write API SERVICES
45% write WEB APPS
*
Go Developer Survey 2020 Results
HELLO GOPHER
package main



import "fmt"



func main() {

fmt.Println("Hello Gopher!")
}
Run Code
go build hellogopher.go // 1. Compile code

./hellogopher // 2. Run binary
go run hellogopher.go // Compile code + run binary
DEVELOPMENT
JetBrains
GoLand
Visual
Studio Code
Vim Go
5 FACTS ABOUT GO
1 static type system
2 garbage collection
3 no inheritance
4 built-in concurrency
5 native execution 

Linux,
Win, z/OS, 386, amd64, ARM, wasm, ...
VARIABLES, SLICES, LOOPS
// Variable
var kitty string = "Kitty"
bella := "Bella"
1
2
3
4
// Array (fixed length)
5
namesArray := [3]string{kitty, bella, "Cleo"}
6
7
// Slice (variable length)
8
namesSlice := make([]string, 2)
9
namesSlice[0] = kitty
10
11
// Loop
12
for i, name := range namesSlice {
13
fmt.Println("Hello " + name + "!")
14
}
15
// Array (fixed length)
namesArray := [3]string{kitty, bella, "Cleo"}
// Variable
1
var kitty string = "Kitty"
2
bella := "Bella"
3
4
5
6
7
// Slice (variable length)
8
namesSlice := make([]string, 2)
9
namesSlice[0] = kitty
10
11
// Loop
12
for i, name := range namesSlice {
13
fmt.Println("Hello " + name + "!")
14
}
15
// Slice (variable length)
namesSlice := make([]string, 2)
namesSlice[0] = kitty
// Variable
1
var kitty string = "Kitty"
2
bella := "Bella"
3
4
// Array (fixed length)
5
namesArray := [3]string{kitty, bella, "Cleo"}
6
7
8
9
10
11
// Loop
12
for i, name := range namesSlice {
13
fmt.Println("Hello " + name + "!")
14
}
15
// Loop
for i, name := range namesSlice {
fmt.Println("Hello " + name + "!")
}
// Variable
1
var kitty string = "Kitty"
2
bella := "Bella"
3
4
// Array (fixed length)
5
namesArray := [3]string{kitty, bella, "Cleo"}
6
7
// Slice (variable length)
8
namesSlice := make([]string, 2)
9
namesSlice[0] = kitty
10
11
12
13
14
15
STRUCT
type Cat struct {
Name string
}
1
2
3
4
func main() {
5
c := Cat{Name: "Kitty"}
6
fmt.Println("Hello " + c.Name + "!")
7
}
8
c := Cat{Name: "Kitty"}
fmt.Println("Hello " + c.Name + "!")
type Cat struct {
1
Name string
2
}
3
4
func main() {
5
6
7
}
8
type Cat struct {
Name string
}
func main() {
c := Cat{Name: "Kitty"}
fmt.Println("Hello " + c.Name + "!")
}
1
2
3
4
5
6
7
8
ERRORS
// Error as return value
func (c Cat) feed(food string) error {
if c.Name == "Kitty" && food != "Steak Tartare" {
return errors.New("Won't eat!")
}
return nil
}
1
2
3
4
5
6
7
8
func main() {
9
c := Cat{Name: "Kitty"}
10
11
// Handle error
12
err := c.feed("Caviar")
13
if err != nil {
14
fmt.Printf("%v won't eat it.", c.Name)
15
}
16
}
17
// Handle error
err := c.feed("Caviar")
if err != nil {
fmt.Printf("%v won't eat it.", c.Name)
}
}
// Error as return value
1
func (c Cat) feed(food string) error {
2
if c.Name == "Kitty" && food != "Steak Tartare" {
3
return errors.New("Won't eat!")
4
}
5
return nil
6
}
7
8
func main() {
9
c := Cat{Name: "Kitty"}
10
11
12
13
14
15
16
17
THE CATS APP
CATS APP 

API
SET UP CATS APP
# Create directory

mkdir cats

cd cats
# Enable dependency tracking

go mod init goday.com/cats
# Create go file

touch main.go
CAT API SIMPLE
func main() {
http.HandleFunc("/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("/api/cats", catAPIHandler)
7
http.ListenAndServe(":8080", nil)
8
}
9
CAT API WITH JSON
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
cats := make([]Cat, 1)
cats[0] = Cat{Name: "Ginger"}
json.NewEncoder(w).Encode(c)
type Cat struct {
1
Name string
2
}
3
4
5
6
7
8
}
9
10
func main() {
11
http.HandleFunc("/api/cats", catAPIHandler)
12
http.ListenAndServe(":8080", nil)
13
}
14
type Cat struct {
Name string
}
1
2
3
4
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
5
cats := make([]Cat, 1)
6
cats[0] = Cat{Name: "Ginger"}
7
json.NewEncoder(w).Encode(c)
8
}
9
10
func main() {
11
http.HandleFunc("/api/cats", catAPIHandler)
12
http.ListenAndServe(":8080", nil)
13
}
14
type Cat struct {
Name string
}
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
cats := make([]Cat, 1)
cats[0] = Cat{Name: "Ginger"}
json.NewEncoder(w).Encode(c)
1
2
3
4
5
6
7
8
}
9
10
func main() {
11
http.HandleFunc("/api/cats", catAPIHandler)
12
http.ListenAndServe(":8080", nil)
13
}
14
type Cat struct {
Name string
}
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
cats := make([]Cat, 1)
cats[0] = Cat{Name: "Ginger"}
json.NewEncoder(w).Encode(c)
}
func main() {
http.HandleFunc("/api/cats", catAPIHandler)
http.ListenAndServe(":8080", nil)
1
2
3
4
5
6
7
8
9
10
11
12
13
}
14
CAT API WITH 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
CAT API WITH JSON
type Cat struct {
Name string
}
func catAPIHandler(w http.ResponseWriter, r *http.Request) {
cats := make([]Cat, 1)
cats[0] = Cat{Name: "Ginger"}
json.NewEncoder(w).Encode(cats)
1
2 `json:"name"`
3
4
5
6
7
8
}
9
10
func main() {
11
http.HandleFunc("/api/cats", catAPIHandler)
12
http.ListenAndServe(":8080", nil)
13
}
14
TEST CAT API cat_api_test.go
func TestCatAPIHandler(t *testing.T) {
}
1
// 1. Create test request
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
// 2. Create recorder (which satisfies http.ResponseWriter)
5
recorder := httptest.NewRecorder()
6
7
// 3. Invoke handler
8
catAPIHandler(recorder, req)
9
10
// 4. Check the response
11
if recorder.Code != http.StatusOK {
12
t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta
13
}
14
15
// 1. Create test request
req, _ := http.NewRequest("GET", "/api/cats", nil)
func TestCatAPIHandler(t *testing.T) {
1
2
3
4
// 2. Create recorder (which satisfies http.ResponseWriter)
5
recorder := httptest.NewRecorder()
6
7
// 3. Invoke handler
8
catAPIHandler(recorder, req)
9
10
// 4. Check the response
11
if recorder.Code != http.StatusOK {
12
t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta
13
}
14
}
15
// 2. Create recorder (which satisfies http.ResponseWriter)
recorder := httptest.NewRecorder()
func TestCatAPIHandler(t *testing.T) {
1
// 1. Create test request
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
5
6
7
// 3. Invoke handler
8
catAPIHandler(recorder, req)
9
10
// 4. Check the response
11
if recorder.Code != http.StatusOK {
12
t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta
13
}
14
}
15
// 3. Invoke handler
catAPIHandler(recorder, req)
func TestCatAPIHandler(t *testing.T) {
1
// 1. Create test request
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
// 2. Create recorder (which satisfies http.ResponseWriter)
5
recorder := httptest.NewRecorder()
6
7
8
9
10
// 4. Check the response
11
if recorder.Code != http.StatusOK {
12
t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta
13
}
14
}
15
// 4. Check the response
if recorder.Code != http.StatusOK {
t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta
}
func TestCatAPIHandler(t *testing.T) {
1
// 1. Create test request
2
req, _ := http.NewRequest("GET", "/api/cats", nil)
3
4
// 2. Create recorder (which satisfies http.ResponseWriter)
5
recorder := httptest.NewRecorder()
6
7
// 3. Invoke handler
8
catAPIHandler(recorder, req)
9
10
11
12
13
14
}
15
func TestCatAPIHandler(t *testing.T) {
// 1. Create test request
req, _ := http.NewRequest("GET", "/api/cats", nil)
// 2. Create recorder (which satisfies http.ResponseWriter)
recorder := httptest.NewRecorder()
// 3. Invoke handler
catAPIHandler(recorder, req)
// 4. Check the response
if recorder.Code != http.StatusOK {
t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
RUN TEST
# Run tests
go test -v ./...
1
2
=== RUN TestCatAPIHandler
3
--- PASS: TestCatAPIHandler (0.00s)
4
PASS
5
coverage: 50.0% of statements
6
ok devopscon.com/cats 0.127s coverage: 50.0% of stateme
7
=== RUN TestCatAPIHandler
--- PASS: TestCatAPIHandler (0.00s)
PASS
coverage: 50.0% of statements
ok devopscon.com/cats 0.127s coverage: 50.0% of statem
# Run tests
1
go test -v ./...
2
3
4
5
6
7
BUILD WITH Makefile
build:
go build -o dist/"${BIN_FILE}"
.DEFAULT_GOAL := build
1
BIN_FILE=cats
2
3
4
5
6
test:
7
go test -v ./...
8
9
run:
10
./"${BIN_FILE}"
11
12
clean:
13
go clean
14
test:
go test -v ./...
.DEFAULT_GOAL := build
1
BIN_FILE=cats
2
3
build:
4
go build -o dist/"${BIN_FILE}"
5
6
7
8
9
run:
10
./"${BIN_FILE}"
11
12
clean:
13
go clean
14
run:
./"${BIN_FILE}"
.DEFAULT_GOAL := build
1
BIN_FILE=cats
2
3
build:
4
go build -o dist/"${BIN_FILE}"
5
6
test:
7
go test -v ./...
8
9
10
11
12
clean:
13
go clean
14
clean:
go clean
.DEFAULT_GOAL := build
1
BIN_FILE=cats
2
3
build:
4
go build -o dist/"${BIN_FILE}"
5
6
test:
7
go test -v ./...
8
9
run:
10
./"${BIN_FILE}"
11
12
13
14
.DEFAULT_GOAL := build
BIN_FILE=cats
build:
go build -o dist/"${BIN_FILE}"
test:
go test -v ./...
run:
./"${BIN_FILE}"
clean:
go clean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
DEMO
CATS APP 

WEB
CATS HANDLER BASIC TEMPLATE SETUP
func indexHandler(w http.ResponseWriter, r *http.Request) {
var tpl = template.Must(template.ParseFiles("index.html"))
tpl.Execute(w, nil)
1
2
3
}
4
5
func main() {
6
http.HandleFunc("/", indexHandler)
7
http.ListenAndServe(":8080", nil)
8
}
9
func indexHandler(w http.ResponseWriter, r *http.Request) {
var tpl = template.Must(template.ParseFiles("index.html"))
tpl.Execute(w, nil)
}
func main() {
http.HandleFunc("/", indexHandler)
http.ListenAndServe(":8080", nil)
}
1
2
3
4
5
6
7
8
9
func indexHandler(w http.ResponseWriter, r *http.Request) {
var tpl = template.Must(template.ParseFiles("index.html"))
tpl.Execute(w, nil)
}
func main() {
http.HandleFunc("/", indexHandler)
http.ListenAndServe(":8080", nil)
}
1
2
3
4
5
6
7
8
9
CATS HANDLER WITH MULTIPLEXER
mux := http.NewServeMux()
mux.HandleFunc("/", indexHandler)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
var tpl = template.Must(template.ParseFiles("index.html"))
2
tpl.Execute(w, nil)
3
}
4
5
func main() {
6
7
8
9
http.ListenAndServe(":8080", mux)
10
}
11
http.ListenAndServe(":8080", mux)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
var tpl = template.Must(template.ParseFiles("index.html"))
2
tpl.Execute(w, nil)
3
}
4
5
func main() {
6
mux := http.NewServeMux()
7
mux.HandleFunc("/", indexHandler)
8
9
10
}
11
func indexHandler(w http.ResponseWriter, r *http.Request) {
var tpl = template.Must(template.ParseFiles("index.html"))
tpl.Execute(w, nil)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", indexHandler)
http.ListenAndServe(":8080", mux)
}
1
2
3
4
5
6
7
8
9
10
11
SERVE FILES FROM FILESYSTEM
// Serve files
fs := http.FileServer(http.Dir("assets"))
mux.Handle("/assets/", http.StripPrefix("/assets/", fs))
func main() {
1
mux := http.NewServeMux()
2
mux.HandleFunc("/", indexHandler)
3
4
5
6
7
8
http.ListenAndServe(":8080", mux)
9
}
10
SERVE FILES EMBEDDED IN BINARY
// Serve files
mux.Handle("/assets/", http.FileServer(http.FS(assets)))
//go:embed assets
1
var assets embed.FS
2
3
func main() {
4
mux := http.NewServeMux()
5
mux.HandleFunc("/", indexHandler)
6
7
8
9
10
http.ListenAndServe(":8080", mux)
11
}
12
//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
mux.HandleFunc("/", indexHandler)
mux.Handle("/assets/", http.FileServer(http.FS(assets)))
//go:embed assets
1
var assets embed.FS
2
3
func main() {
4
mux := http.NewServeMux()
5
6
7
// Serve files
8
9
10
http.ListenAndServe(":8080", mux)
11
}
12
HANDLER AND HANDLEFUNC
CATS HANDLER TEMPLATE WITH DATA
main.go
type Cat struct {

Name string

}



func indexHandler(w ResponseWriter, r *Request) {
// Create cat slice

cat := make([]Cat, 1)



// Add cat ginger

cat[0] = Cat{Name: "Ginger"}



// Render template

tpl.Execute(w, cat)

}
index.html
<body>

<h1>Cats App</h1>

{{ range. }}

<h2>{{ .Name }}</h2>
{{ end }}

</body>
CATS HANDLER WITH CATS API
Query Cats API
GET https://api.thecatapi.com/v1/breeds?limit=5
[

{

"id": "abys",

"name": "Abyssinian",

"image": {

"url": "https://cdn2.thecatapi.com/images/0XYvRd7oD.jpg
}

},

{

"id": "aege",

"name": "Aegean",

"image": {

"url": "https://cdn2.thecatapi.com/images/ozEvzdVM-.jpg
}

},

...

]
Map JSON
type Cat struct {

ID string `json:"id"`

Name string `json:"name"`

Image struct {

URL string `json:"url"`

} `json:"image"`

}
CATS HANDLER WITH CATS API
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
if err != nil {
http.Error(w, "Cats API error", http.StatusInternalServerError)
return
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
2
3
4
5
6
7
// Create cat slice
8
cat := make([]Cat, 5)
9
10
// Read and parse body
11
defer resp.Body.Close()
12
body, _ := ioutil.ReadAll(resp.Body)
13
json.Unmarshal(body, &cat)
14
15
tpl.Execute(w, cat)
16
}
17
// Create cat slice
cat := make([]Cat, 5)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
2
if err != nil {
3
http.Error(w, "Cats API error", http.StatusInternalServerError)
4
return
5
}
6
7
8
9
10
// Read and parse body
11
defer resp.Body.Close()
12
body, _ := ioutil.ReadAll(resp.Body)
13
json.Unmarshal(body, &cat)
14
15
tpl.Execute(w, cat)
16
}
17
// Read and parse body
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
json.Unmarshal(body, &cat)
func indexHandler(w http.ResponseWriter, r *http.Request) {
1
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
2
if err != nil {
3
http.Error(w, "Cats API error", http.StatusInternalServerError)
4
return
5
}
6
7
// Create cat slice
8
cat := make([]Cat, 5)
9
10
11
12
13
14
15
tpl.Execute(w, cat)
16
}
17
func indexHandler(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5")
if err != nil {
http.Error(w, "Cats API error", http.StatusInternalServerError)
return
}
// Create cat slice
cat := make([]Cat, 5)
// Read and parse body
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
json.Unmarshal(body, &cat)
tpl.Execute(w, cat)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MIDDLEWARE
cross cutting functionality for all requests 

(e.g. logging, authentication)
#
create a chain of handlers 

router => middleware handler => application handler
#
satisfy the interface http.Handler
#
MIDDLEWARE TO LOG REQUESTS
http.ListenAndServe(":8080", loggingMiddleware(mux))
func loggingMiddleware(next http.Handler) http.Handler {
1
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque
2
log.Printf("%v requested URL %v", r.Host, r.URL)
3
next.ServeHTTP(w, r)
4
})
5
}
6
7
func main() {
8
mux := http.NewServeMux()
9
mux.HandleFunc("/", indexHandler)
10
11
12
}
13
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque
log.Printf("%v requested URL %v", r.Host, r.URL)
next.ServeHTTP(w, r)
})
}
1
2
3
4
5
6
7
func main() {
8
mux := http.NewServeMux()
9
mux.HandleFunc("/", indexHandler)
10
11
http.ListenAndServe(":8080", loggingMiddleware(mux))
12
}
13
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque
log.Printf("%v requested URL %v", r.Host, r.URL)
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", indexHandler)
http.ListenAndServe(":8080", loggingMiddleware(mux))
1
2
3
4
5
6
7
8
9
10
11
12
}
13
DEMO
BASICS 

 
Dev Setup
Variables,
Slices, Loops
Struct
Errors
#
#
#
#
CATS APP 

API
Handler (with
JSON)
Http Test
Build
#
#
#
CATS APP 

WEB
Multiplexer
(Router)
File Server
Template
Middleware
#
#
#
#
JAN STAMER
Solution Architect
jan.stamer@comdirect.de

More Related Content

What's hot

OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP haters
Lin Yo-An
 

What's hot (20)

Email Using Plsql
Email Using PlsqlEmail Using Plsql
Email Using Plsql
 
The Ring programming language version 1.5.3 book - Part 25 of 184
The Ring programming language version 1.5.3 book - Part 25 of 184The Ring programming language version 1.5.3 book - Part 25 of 184
The Ring programming language version 1.5.3 book - Part 25 of 184
 
uerj201212
uerj201212uerj201212
uerj201212
 
Cooking pies with Celery
Cooking pies with CeleryCooking pies with Celery
Cooking pies with Celery
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?
 
clap: Command line argument parser for Pharo
clap: Command line argument parser for Pharoclap: Command line argument parser for Pharo
clap: Command line argument parser for Pharo
 
OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP haters
 
Fun with Ruby and Cocoa
Fun with Ruby and CocoaFun with Ruby and Cocoa
Fun with Ruby and Cocoa
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
 
Introducing to Asynchronous Programming
Introducing to Asynchronous  ProgrammingIntroducing to Asynchronous  Programming
Introducing to Asynchronous Programming
 
2016年のPerl (Long version)
2016年のPerl (Long version)2016年のPerl (Long version)
2016年のPerl (Long version)
 
Rust
RustRust
Rust
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Unix Programming with Perl 2
Unix Programming with Perl 2Unix Programming with Perl 2
Unix Programming with Perl 2
 
ssh.isdn.test
ssh.isdn.testssh.isdn.test
ssh.isdn.test
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
The Ring programming language version 1.9 book - Part 37 of 210
The Ring programming language version 1.9 book - Part 37 of 210The Ring programming language version 1.9 book - Part 37 of 210
The Ring programming language version 1.9 book - Part 37 of 210
 
General Functions
General FunctionsGeneral Functions
General Functions
 
Assignment6
Assignment6Assignment6
Assignment6
 
Project in programming
Project in programmingProject in programming
Project in programming
 

Similar to entwickler.de Go Day: Go Web Development 101

Jersey framework
Jersey frameworkJersey framework
Jersey framework
knight1128
 
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
ConFoo
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
Abed Bukhari
 
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxjava compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
priestmanmable
 

Similar to entwickler.de Go Day: Go Web Development 101 (20)

Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2
 
Jersey framework
Jersey frameworkJersey framework
Jersey framework
 
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
 
¿Cómo de sexy puede hacer Backbone mi código?
¿Cómo de sexy puede hacer Backbone mi código?¿Cómo de sexy puede hacer Backbone mi código?
¿Cómo de sexy puede hacer Backbone mi código?
 
ECMeowScript - What's New in JavaScript Explained with Cats (August 14th, 2020)
ECMeowScript - What's New in JavaScript Explained with Cats (August 14th, 2020)ECMeowScript - What's New in JavaScript Explained with Cats (August 14th, 2020)
ECMeowScript - What's New in JavaScript Explained with Cats (August 14th, 2020)
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8
 
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidad
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers Steal
 
Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516
 
My java file
My java fileMy java file
My java file
 
Finch.io - Purely Functional REST API with Finagle
Finch.io - Purely Functional REST API with FinagleFinch.io - Purely Functional REST API with Finagle
Finch.io - Purely Functional REST API with Finagle
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (DPC 2015)
Adding 1.21 Gigawatts to Applications with RabbitMQ (DPC 2015)Adding 1.21 Gigawatts to Applications with RabbitMQ (DPC 2015)
Adding 1.21 Gigawatts to Applications with RabbitMQ (DPC 2015)
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxjava compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8
 
Server1
Server1Server1
Server1
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
Android dev 3
Android dev 3Android dev 3
Android dev 3
 

More from Jan Stamer

More from Jan Stamer (10)

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
 
JAX 2024: Go in der Praxis einsetzen
JAX 2024: Go in der Praxis einsetzenJAX 2024: Go in der Praxis einsetzen
JAX 2024: Go in der Praxis einsetzen
 
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
 
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 05/2023: Go über den Wolken
entwickler.de 05/2023: Go über den Wolkenentwickler.de 05/2023: Go über den Wolken
entwickler.de 05/2023: Go über den Wolken
 
IT-Tage 2021: Java to Go - Google Go für Java-Entwickler
IT-Tage 2021: Java to Go - Google Go für Java-Entwickler IT-Tage 2021: Java to Go - Google Go für Java-Entwickler
IT-Tage 2021: Java to Go - Google Go für Java-Entwickler
 
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
 
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?
 

Recently uploaded

Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
UK Journal
 

Recently uploaded (20)

Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through Observability
 
Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoft
 
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
 
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101
 
Designing for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastDesigning for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at Comcast
 
TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe
 
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
 
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
 
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
 
Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджера
 
Enterprise Knowledge Graphs - Data Summit 2024
Enterprise Knowledge Graphs - Data Summit 2024Enterprise Knowledge Graphs - Data Summit 2024
Enterprise Knowledge Graphs - Data Summit 2024
 
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdfSimplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
 
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdfHow Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
 

entwickler.de Go Day: Go Web Development 101

  • 2. 3 MONTHS to be productive 74% write API SERVICES 45% write WEB APPS * Go Developer Survey 2020 Results
  • 3.
  • 4. HELLO GOPHER package main import "fmt" func main() { fmt.Println("Hello Gopher!") } Run Code go build hellogopher.go // 1. Compile code ./hellogopher // 2. Run binary go run hellogopher.go // Compile code + run binary
  • 6. 5 FACTS ABOUT GO 1 static type system 2 garbage collection 3 no inheritance 4 built-in concurrency 5 native execution Linux, Win, z/OS, 386, amd64, ARM, wasm, ...
  • 7. VARIABLES, SLICES, LOOPS // Variable var kitty string = "Kitty" bella := "Bella" 1 2 3 4 // Array (fixed length) 5 namesArray := [3]string{kitty, bella, "Cleo"} 6 7 // Slice (variable length) 8 namesSlice := make([]string, 2) 9 namesSlice[0] = kitty 10 11 // Loop 12 for i, name := range namesSlice { 13 fmt.Println("Hello " + name + "!") 14 } 15 // Array (fixed length) namesArray := [3]string{kitty, bella, "Cleo"} // Variable 1 var kitty string = "Kitty" 2 bella := "Bella" 3 4 5 6 7 // Slice (variable length) 8 namesSlice := make([]string, 2) 9 namesSlice[0] = kitty 10 11 // Loop 12 for i, name := range namesSlice { 13 fmt.Println("Hello " + name + "!") 14 } 15 // Slice (variable length) namesSlice := make([]string, 2) namesSlice[0] = kitty // Variable 1 var kitty string = "Kitty" 2 bella := "Bella" 3 4 // Array (fixed length) 5 namesArray := [3]string{kitty, bella, "Cleo"} 6 7 8 9 10 11 // Loop 12 for i, name := range namesSlice { 13 fmt.Println("Hello " + name + "!") 14 } 15 // Loop for i, name := range namesSlice { fmt.Println("Hello " + name + "!") } // Variable 1 var kitty string = "Kitty" 2 bella := "Bella" 3 4 // Array (fixed length) 5 namesArray := [3]string{kitty, bella, "Cleo"} 6 7 // Slice (variable length) 8 namesSlice := make([]string, 2) 9 namesSlice[0] = kitty 10 11 12 13 14 15
  • 8. STRUCT type Cat struct { Name string } 1 2 3 4 func main() { 5 c := Cat{Name: "Kitty"} 6 fmt.Println("Hello " + c.Name + "!") 7 } 8 c := Cat{Name: "Kitty"} fmt.Println("Hello " + c.Name + "!") type Cat struct { 1 Name string 2 } 3 4 func main() { 5 6 7 } 8 type Cat struct { Name string } func main() { c := Cat{Name: "Kitty"} fmt.Println("Hello " + c.Name + "!") } 1 2 3 4 5 6 7 8
  • 9. ERRORS // Error as return value func (c Cat) feed(food string) error { if c.Name == "Kitty" && food != "Steak Tartare" { return errors.New("Won't eat!") } return nil } 1 2 3 4 5 6 7 8 func main() { 9 c := Cat{Name: "Kitty"} 10 11 // Handle error 12 err := c.feed("Caviar") 13 if err != nil { 14 fmt.Printf("%v won't eat it.", c.Name) 15 } 16 } 17 // Handle error err := c.feed("Caviar") if err != nil { fmt.Printf("%v won't eat it.", c.Name) } } // Error as return value 1 func (c Cat) feed(food string) error { 2 if c.Name == "Kitty" && food != "Steak Tartare" { 3 return errors.New("Won't eat!") 4 } 5 return nil 6 } 7 8 func main() { 9 c := Cat{Name: "Kitty"} 10 11 12 13 14 15 16 17
  • 11.
  • 13. SET UP CATS APP # Create directory mkdir cats cd cats # Enable dependency tracking go mod init goday.com/cats # Create go file touch main.go
  • 14. CAT API SIMPLE func main() { http.HandleFunc("/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("/api/cats", catAPIHandler) 7 http.ListenAndServe(":8080", nil) 8 } 9
  • 15. CAT API WITH JSON func catAPIHandler(w http.ResponseWriter, r *http.Request) { cats := make([]Cat, 1) cats[0] = Cat{Name: "Ginger"} json.NewEncoder(w).Encode(c) type Cat struct { 1 Name string 2 } 3 4 5 6 7 8 } 9 10 func main() { 11 http.HandleFunc("/api/cats", catAPIHandler) 12 http.ListenAndServe(":8080", nil) 13 } 14 type Cat struct { Name string } 1 2 3 4 func catAPIHandler(w http.ResponseWriter, r *http.Request) { 5 cats := make([]Cat, 1) 6 cats[0] = Cat{Name: "Ginger"} 7 json.NewEncoder(w).Encode(c) 8 } 9 10 func main() { 11 http.HandleFunc("/api/cats", catAPIHandler) 12 http.ListenAndServe(":8080", nil) 13 } 14 type Cat struct { Name string } func catAPIHandler(w http.ResponseWriter, r *http.Request) { cats := make([]Cat, 1) cats[0] = Cat{Name: "Ginger"} json.NewEncoder(w).Encode(c) 1 2 3 4 5 6 7 8 } 9 10 func main() { 11 http.HandleFunc("/api/cats", catAPIHandler) 12 http.ListenAndServe(":8080", nil) 13 } 14 type Cat struct { Name string } func catAPIHandler(w http.ResponseWriter, r *http.Request) { cats := make([]Cat, 1) cats[0] = Cat{Name: "Ginger"} json.NewEncoder(w).Encode(c) } func main() { http.HandleFunc("/api/cats", catAPIHandler) http.ListenAndServe(":8080", nil) 1 2 3 4 5 6 7 8 9 10 11 12 13 } 14
  • 16. CAT API WITH 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
  • 17. CAT API WITH JSON type Cat struct { Name string } func catAPIHandler(w http.ResponseWriter, r *http.Request) { cats := make([]Cat, 1) cats[0] = Cat{Name: "Ginger"} json.NewEncoder(w).Encode(cats) 1 2 `json:"name"` 3 4 5 6 7 8 } 9 10 func main() { 11 http.HandleFunc("/api/cats", catAPIHandler) 12 http.ListenAndServe(":8080", nil) 13 } 14
  • 18. TEST CAT API cat_api_test.go func TestCatAPIHandler(t *testing.T) { } 1 // 1. Create test request 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 // 2. Create recorder (which satisfies http.ResponseWriter) 5 recorder := httptest.NewRecorder() 6 7 // 3. Invoke handler 8 catAPIHandler(recorder, req) 9 10 // 4. Check the response 11 if recorder.Code != http.StatusOK { 12 t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta 13 } 14 15 // 1. Create test request req, _ := http.NewRequest("GET", "/api/cats", nil) func TestCatAPIHandler(t *testing.T) { 1 2 3 4 // 2. Create recorder (which satisfies http.ResponseWriter) 5 recorder := httptest.NewRecorder() 6 7 // 3. Invoke handler 8 catAPIHandler(recorder, req) 9 10 // 4. Check the response 11 if recorder.Code != http.StatusOK { 12 t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta 13 } 14 } 15 // 2. Create recorder (which satisfies http.ResponseWriter) recorder := httptest.NewRecorder() func TestCatAPIHandler(t *testing.T) { 1 // 1. Create test request 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 5 6 7 // 3. Invoke handler 8 catAPIHandler(recorder, req) 9 10 // 4. Check the response 11 if recorder.Code != http.StatusOK { 12 t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta 13 } 14 } 15 // 3. Invoke handler catAPIHandler(recorder, req) func TestCatAPIHandler(t *testing.T) { 1 // 1. Create test request 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 // 2. Create recorder (which satisfies http.ResponseWriter) 5 recorder := httptest.NewRecorder() 6 7 8 9 10 // 4. Check the response 11 if recorder.Code != http.StatusOK { 12 t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta 13 } 14 } 15 // 4. Check the response if recorder.Code != http.StatusOK { t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta } func TestCatAPIHandler(t *testing.T) { 1 // 1. Create test request 2 req, _ := http.NewRequest("GET", "/api/cats", nil) 3 4 // 2. Create recorder (which satisfies http.ResponseWriter) 5 recorder := httptest.NewRecorder() 6 7 // 3. Invoke handler 8 catAPIHandler(recorder, req) 9 10 11 12 13 14 } 15 func TestCatAPIHandler(t *testing.T) { // 1. Create test request req, _ := http.NewRequest("GET", "/api/cats", nil) // 2. Create recorder (which satisfies http.ResponseWriter) recorder := httptest.NewRecorder() // 3. Invoke handler catAPIHandler(recorder, req) // 4. Check the response if recorder.Code != http.StatusOK { t.Errorf("Wrong status: got %v expected %v", recorder.Code, http.Sta } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  • 19. RUN TEST # Run tests go test -v ./... 1 2 === RUN TestCatAPIHandler 3 --- PASS: TestCatAPIHandler (0.00s) 4 PASS 5 coverage: 50.0% of statements 6 ok devopscon.com/cats 0.127s coverage: 50.0% of stateme 7 === RUN TestCatAPIHandler --- PASS: TestCatAPIHandler (0.00s) PASS coverage: 50.0% of statements ok devopscon.com/cats 0.127s coverage: 50.0% of statem # Run tests 1 go test -v ./... 2 3 4 5 6 7
  • 20. BUILD WITH Makefile build: go build -o dist/"${BIN_FILE}" .DEFAULT_GOAL := build 1 BIN_FILE=cats 2 3 4 5 6 test: 7 go test -v ./... 8 9 run: 10 ./"${BIN_FILE}" 11 12 clean: 13 go clean 14 test: go test -v ./... .DEFAULT_GOAL := build 1 BIN_FILE=cats 2 3 build: 4 go build -o dist/"${BIN_FILE}" 5 6 7 8 9 run: 10 ./"${BIN_FILE}" 11 12 clean: 13 go clean 14 run: ./"${BIN_FILE}" .DEFAULT_GOAL := build 1 BIN_FILE=cats 2 3 build: 4 go build -o dist/"${BIN_FILE}" 5 6 test: 7 go test -v ./... 8 9 10 11 12 clean: 13 go clean 14 clean: go clean .DEFAULT_GOAL := build 1 BIN_FILE=cats 2 3 build: 4 go build -o dist/"${BIN_FILE}" 5 6 test: 7 go test -v ./... 8 9 run: 10 ./"${BIN_FILE}" 11 12 13 14 .DEFAULT_GOAL := build BIN_FILE=cats build: go build -o dist/"${BIN_FILE}" test: go test -v ./... run: ./"${BIN_FILE}" clean: go clean 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  • 21. DEMO
  • 23. CATS HANDLER BASIC TEMPLATE SETUP func indexHandler(w http.ResponseWriter, r *http.Request) { var tpl = template.Must(template.ParseFiles("index.html")) tpl.Execute(w, nil) 1 2 3 } 4 5 func main() { 6 http.HandleFunc("/", indexHandler) 7 http.ListenAndServe(":8080", nil) 8 } 9 func indexHandler(w http.ResponseWriter, r *http.Request) { var tpl = template.Must(template.ParseFiles("index.html")) tpl.Execute(w, nil) } func main() { http.HandleFunc("/", indexHandler) http.ListenAndServe(":8080", nil) } 1 2 3 4 5 6 7 8 9 func indexHandler(w http.ResponseWriter, r *http.Request) { var tpl = template.Must(template.ParseFiles("index.html")) tpl.Execute(w, nil) } func main() { http.HandleFunc("/", indexHandler) http.ListenAndServe(":8080", nil) } 1 2 3 4 5 6 7 8 9
  • 24. CATS HANDLER WITH MULTIPLEXER mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 var tpl = template.Must(template.ParseFiles("index.html")) 2 tpl.Execute(w, nil) 3 } 4 5 func main() { 6 7 8 9 http.ListenAndServe(":8080", mux) 10 } 11 http.ListenAndServe(":8080", mux) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 var tpl = template.Must(template.ParseFiles("index.html")) 2 tpl.Execute(w, nil) 3 } 4 5 func main() { 6 mux := http.NewServeMux() 7 mux.HandleFunc("/", indexHandler) 8 9 10 } 11 func indexHandler(w http.ResponseWriter, r *http.Request) { var tpl = template.Must(template.ParseFiles("index.html")) tpl.Execute(w, nil) } func main() { mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) http.ListenAndServe(":8080", mux) } 1 2 3 4 5 6 7 8 9 10 11
  • 25. SERVE FILES FROM FILESYSTEM // Serve files fs := http.FileServer(http.Dir("assets")) mux.Handle("/assets/", http.StripPrefix("/assets/", fs)) func main() { 1 mux := http.NewServeMux() 2 mux.HandleFunc("/", indexHandler) 3 4 5 6 7 8 http.ListenAndServe(":8080", mux) 9 } 10
  • 26. SERVE FILES EMBEDDED IN BINARY // Serve files mux.Handle("/assets/", http.FileServer(http.FS(assets))) //go:embed assets 1 var assets embed.FS 2 3 func main() { 4 mux := http.NewServeMux() 5 mux.HandleFunc("/", indexHandler) 6 7 8 9 10 http.ListenAndServe(":8080", mux) 11 } 12 //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 mux.HandleFunc("/", indexHandler) mux.Handle("/assets/", http.FileServer(http.FS(assets))) //go:embed assets 1 var assets embed.FS 2 3 func main() { 4 mux := http.NewServeMux() 5 6 7 // Serve files 8 9 10 http.ListenAndServe(":8080", mux) 11 } 12
  • 28. CATS HANDLER TEMPLATE WITH DATA main.go type Cat struct { Name string } func indexHandler(w ResponseWriter, r *Request) { // Create cat slice cat := make([]Cat, 1) // Add cat ginger cat[0] = Cat{Name: "Ginger"} // Render template tpl.Execute(w, cat) } index.html <body> <h1>Cats App</h1> {{ range. }} <h2>{{ .Name }}</h2> {{ end }} </body>
  • 29.
  • 30. CATS HANDLER WITH CATS API Query Cats API GET https://api.thecatapi.com/v1/breeds?limit=5 [ { "id": "abys", "name": "Abyssinian", "image": { "url": "https://cdn2.thecatapi.com/images/0XYvRd7oD.jpg } }, { "id": "aege", "name": "Aegean", "image": { "url": "https://cdn2.thecatapi.com/images/ozEvzdVM-.jpg } }, ... ] Map JSON type Cat struct { ID string `json:"id"` Name string `json:"name"` Image struct { URL string `json:"url"` } `json:"image"` }
  • 31.
  • 32. CATS HANDLER WITH CATS API resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") if err != nil { http.Error(w, "Cats API error", http.StatusInternalServerError) return } func indexHandler(w http.ResponseWriter, r *http.Request) { 1 2 3 4 5 6 7 // Create cat slice 8 cat := make([]Cat, 5) 9 10 // Read and parse body 11 defer resp.Body.Close() 12 body, _ := ioutil.ReadAll(resp.Body) 13 json.Unmarshal(body, &cat) 14 15 tpl.Execute(w, cat) 16 } 17 // Create cat slice cat := make([]Cat, 5) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") 2 if err != nil { 3 http.Error(w, "Cats API error", http.StatusInternalServerError) 4 return 5 } 6 7 8 9 10 // Read and parse body 11 defer resp.Body.Close() 12 body, _ := ioutil.ReadAll(resp.Body) 13 json.Unmarshal(body, &cat) 14 15 tpl.Execute(w, cat) 16 } 17 // Read and parse body defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) json.Unmarshal(body, &cat) func indexHandler(w http.ResponseWriter, r *http.Request) { 1 resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") 2 if err != nil { 3 http.Error(w, "Cats API error", http.StatusInternalServerError) 4 return 5 } 6 7 // Create cat slice 8 cat := make([]Cat, 5) 9 10 11 12 13 14 15 tpl.Execute(w, cat) 16 } 17 func indexHandler(w http.ResponseWriter, r *http.Request) { resp, err := http.Get("https://api.thecatapi.com/v1/breeds?limit=5") if err != nil { http.Error(w, "Cats API error", http.StatusInternalServerError) return } // Create cat slice cat := make([]Cat, 5) // Read and parse body defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) json.Unmarshal(body, &cat) tpl.Execute(w, cat) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  • 33. MIDDLEWARE cross cutting functionality for all requests (e.g. logging, authentication) # create a chain of handlers router => middleware handler => application handler # satisfy the interface http.Handler #
  • 34. MIDDLEWARE TO LOG REQUESTS http.ListenAndServe(":8080", loggingMiddleware(mux)) func loggingMiddleware(next http.Handler) http.Handler { 1 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque 2 log.Printf("%v requested URL %v", r.Host, r.URL) 3 next.ServeHTTP(w, r) 4 }) 5 } 6 7 func main() { 8 mux := http.NewServeMux() 9 mux.HandleFunc("/", indexHandler) 10 11 12 } 13 func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque log.Printf("%v requested URL %v", r.Host, r.URL) next.ServeHTTP(w, r) }) } 1 2 3 4 5 6 7 func main() { 8 mux := http.NewServeMux() 9 mux.HandleFunc("/", indexHandler) 10 11 http.ListenAndServe(":8080", loggingMiddleware(mux)) 12 } 13 func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Reque log.Printf("%v requested URL %v", r.Host, r.URL) next.ServeHTTP(w, r) }) } func main() { mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) http.ListenAndServe(":8080", loggingMiddleware(mux)) 1 2 3 4 5 6 7 8 9 10 11 12 } 13
  • 35. DEMO
  • 36. BASICS   Dev Setup Variables, Slices, Loops Struct Errors # # # # CATS APP API Handler (with JSON) Http Test Build # # # CATS APP WEB Multiplexer (Router) File Server Template Middleware # # # #
  • 37.