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

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 184Mahmoud Samir Fayed
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?Adam Dudczak
 
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 PharoESUG
 
OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersLin Yo-An
 
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 kotlinAhmad Arif Faizin
 
2016年のPerl (Long version)
2016年のPerl (Long version)2016年のPerl (Long version)
2016年のPerl (Long version)charsbar
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my dayTor Ivry
 
Unix Programming with Perl 2
Unix Programming with Perl 2Unix Programming with Perl 2
Unix Programming with Perl 2Kazuho Oku
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Lin Yo-An
 
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 210Mahmoud Samir Fayed
 

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

Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2markstory
 
Jersey framework
Jersey frameworkJersey framework
Jersey frameworkknight1128
 
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
 
¿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?jaespinmora
 
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)Tomomi Imura
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Wilson Su
 
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...dantleech
 
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 modularidadDavid Gómez García
 
Great Developers Steal
Great Developers StealGreat Developers Steal
Great Developers StealBen Scofield
 
Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516SOAT
 
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 FinagleVladimir Kostyukov
 
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)James Titcumb
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxjava compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxpriestmanmable
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptVisual Engineering
 
Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8Wilson Su
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot CampTroy Miles
 

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

JAX 2024: Go-über-den-Wolken und in der Cloud
JAX 2024: Go-über-den-Wolken und in der CloudJAX 2024: Go-über-den-Wolken und in der Cloud
JAX 2024: Go-über-den-Wolken und in der CloudJan Stamer
 
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 einsetzenJan Stamer
 
W-JAX 2023: Go über den Wolken
W-JAX 2023: Go über den WolkenW-JAX 2023: Go über den Wolken
W-JAX 2023: Go über den WolkenJan Stamer
 
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. JavaCloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. Java
CloudLand 2023: Rock, Paper, Scissors Cloud Competition - Go vs. JavaJan Stamer
 
entwickler.de 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 WolkenJan Stamer
 
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 Jan Stamer
 
JCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web AppsJCON 2021: Turbo powered Web Apps
JCON 2021: Turbo powered Web AppsJan Stamer
 
DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101DevOpsCon 2021: Go Web Development 101
DevOpsCon 2021: Go Web Development 101Jan Stamer
 
Karlsruher Entwicklertag 2021: Turbo powered Web Apps
Karlsruher Entwicklertag 2021: Turbo powered Web AppsKarlsruher Entwicklertag 2021: Turbo powered Web Apps
Karlsruher Entwicklertag 2021: Turbo powered Web AppsJan Stamer
 
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?
Jugs HH: Elefant unter Strom - von OldSQL über NoSQL zu NewSQL?Jan Stamer
 

More from Jan Stamer (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

Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 

Recently uploaded (20)

Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 

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.