Damiano Petrungaro
Italy
source: www.vidiani.com
Tivoli (RM)
source: www.livitaly.com
Tivoli (RM)
source: www.romaest.org
Tivoli (RM)
source: www.tivolitouring.com
Tivoli (RM)
source: www.confinelive.it
Tivoli (RM)
source: www.greenparkmadama.it
Go, also known as Golang is a statically typed, compiled programming language designed at Google.
Go is syntactically similar to C, but with memory safety, garbage collection, structural typing, and CSP-style concurrency.
package main
import (
"regexp"
)
const globalConstant = "a global string"
const r = regexp.MustCompile("") // const initializer regexp.MustCompile("") is not a constant
func main() {
const name string = "Golang"
const version float64 = 1.13
const major int = 1
// more code here ...
}
// With type inference
func main() {
const name = "Golang"
const version = 1.13
const major = 1
// more code here ...
}
package main
import "regexp"
var globalVariable = "a global string"
var aGlobalRegex = regexp.MustCompile("...")
func main() {
var name string = "Golang"
var version float64 = 1.13
var major int = 1
// more code here ...
}
// With type inference
func main() {
var name = "Golang"
var version = 1.13
var major = 1
// more code here ...
}
// With short declaration
func main() {
name := "Golang"
version := 1.13
major := 1
// more code here ...
}
// With zero-value
func main() {
var name string // ""
var version float64 // 0.0
var major int // 0
// more code here ...
}
package main
// string
// bool
// int8
// uint8(byte)
// int16
// uint16
// int32(rune)
// uint32
// int64
// uint64
// int
// uint
// uintptr
// float32
// float64
// complex64
// complex128
package main
import "fmt"
// As zero-value
func main() {
var anArray [1]int
var aSlice []int
var aMap map[string]int
}
// With composite literal
func main() {
anArray := [1]int{2}
aSlice := []string{"value"}
aMap := map[string]int{"age": 20}
}
// With length and capacity
func main() {
var aSlice = make([]string, 2, 10)
var anotherSlice = new([]string)
}
// What's inside?
func main() {
var aSlice = make([]string, 4, 5)
var anEmptySlice = make([]string, 0, 10)
var aPointerToSlice = new([]string)
fmt.Printf("%#v\n", aSlice) // []string{"", "", "", ""}
fmt.Printf("%#v\n", anEmptySlice) // []string{}
fmt.Printf("%#v\n", aPointerToSlice) // &[]string(nil)
}
package main
import "fmt"
type username string
type printUsernameFunc func(username) bool
func printUsername(u username) bool {
// print the username
return true
}
func main() {
mario := username("mario")
printUsername(mario)
printUsername("luigi")
}
func main() {
complexfunction(printUsername)
}
func complexfunction(fn printUsernameFunc) {
mario := username("mario")
ok := fn(mario)
fmt.Println(ok)
ok = fn("luigi")
fmt.Println(ok)
}
package main
// A simple if statement
func main() {
a := 1
if a > 10 {
// Do something
}
// Continue here
}
// An if/else statement
func main() {
i := len("Mario")
if i < 10 {
// Do something
} else if i > 10 {
// Do something
} else {
// Do something
}
}
// A better if/else statement
func main() {
i := len("Mario")
if i < 10 {
// Do something
return
}
if i > 10 {
// Do something
return
}
// Do something
}
package main
// A simple switch statement
func main() {
name := "Mario"
switch name {
case "Mario":
// Do something
case "Luigi":
// Do something
default:
// Do something
}
}
// A simple switch statement with assignment
func main() {
var name interface{}
name = "Mario"
switch t := name.(type) {
case string:
// Do something
case int:
// Do something
default:
// Do something
}
}
package main
// A simple for loop
func main() {
for i := 0; i > 10; i++ {
// Do something
}
}
package main
// A simple for loop (again)
func main() {
list := []int{1, 10, 234, 63, 32, 8, 24, 8}
for i, v := range list {
// Do something
}
}
// A simple for loop (again) ignoring the index
func main() {
list := []int{1, 10, 234, 63, 32, 8, 24, 8}
for _, v := range list {
// Do something
}
}
package main
// A simple for loop (again)
func main() {
stop := false
for !stop {
// Do something
stop = true
}
}
package main
import (
"fmt"
"os/exec"
)
// A simple function
func funcName() {
// Do something
}
// With a value
func funcName(i int) {
// Do something
}
// With three integers
func funcName(a, b, c int) {
// Do something
}
// With an integer and a string
func funcName(i int, s string) {
// Do something
}
// With a return type
func funcName(i int, s string) bool {
return false
}
// With n return types :wat:
func funcName(i int, s string) (string, bool) {
return "", true
}
// With an error
func funcName(i int, s string) (string, error) {
return "", exec.ErrNotFound
}
// With named return values
func funcName() (name string, surname string, nickname string) {
return
}
// With a named return value changed
func funcName() (name string, surname string, nickname string) {
name = "Mario"
return
}
// Lambda
func main() {
a := func(name string) {
fmt.Println(name)
}
a("Mario")
a("Luigi")
func(name string) {
fmt.Println(name)
}("Peach")
}
package main
import "fmt"
func main() {
defer printZero()
printOne()
printTwo()
}
func printZero() {
fmt.Println(0)
}
func printOne() {
fmt.Println(1)
}
func printTwo() {
fmt.Println(2)
}
package main
import (
"fmt"
)
func main() {
var s2 = new(string)
*s2 = "another value"
print(s2)
}
func print(s *string) {
fmt.Println(s)
}
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
in10Seconds := now.Add(10 * time.Second)
fmt.Println(now.Unix(), in10Seconds.Unix())
}
func main() {
now := time.Now()
in10Seconds := addTenSeconds(now)
fmt.Println(now.Unix(), in10Seconds.Unix())
}
func addTenSeconds(t time.Time) time.Time {
return t.Add(10 * time.Second)
}
package main
import (
"fmt"
"net/http"
)
func main() {
const url = "http://google.com"
req, err := http.NewRequest(http.MethodGet, "http://google.com", nil)
if err != nil {
fmt.Println("an error occurred", err)
return
}
fmt.Println(req.URL.String())
}
func main() {
const url = "http://google.com"
req, err := NewRequest(http.MethodGet, "http://google.com")
if err != nil {
fmt.Println("an error occurred", err)
return
}
fmt.Println(req.URL.String())
}
func NewRequest(method, url string) (*http.Request, error) {
return http.NewRequest(http.MethodGet, url, nil)
}
Think about the usage
Think about the performance
Show me the benchmarks!
package main
import (
"fmt"
"time"
)
type user struct {
firstName string
lastName string
birthDate birthDate
}
type birthDate struct {
t time.Time
}
func main() {
u := user{
firstName: "Mario",
lastName: "Super",
birthDate: birthDate{
time.Now(),
},
}
fmt.Println(u.firstName, u.lastName, u.birthDate.t.Unix())
}
// Without keys
func main() {
u := user{
"Mario",
"Super",
birthDate{
time.Now(),
},
}
fmt.Println(u.firstName, u.lastName, u.birthDate.t.Unix())
}
// With zero values
func main() {
u := user{}
fmt.Println(u.firstName, u.lastName, u.birthDate.t.Unix())
}
package main
import (
"fmt"
"time"
)
type user struct {
firstName string
lastName string
birthDate *birthDate
}
type birthDate struct {
t time.Time
}
func main() {
u := user{
firstName: "Mario",
lastName: "Super",
birthDate: &birthDate{
time.Now(),
},
}
fmt.Println(u.firstName, u.lastName, u.birthDate.t.Unix())
}
// Without keys
func main() {
u := user{
"Mario",
"Super",
&birthDate{
time.Now(),
},
}
fmt.Println(u.firstName, u.lastName, u.birthDate.t.Unix())
}
// With zero values
func main() {
u := user{}
// panic: runtime error: invalid memory address or nil pointer dereference
fmt.Println(u.firstName, u.lastName, u.birthDate.t.Unix())
}
Used to build structs
package main
import "time"
type userName struct {
v string
t time.Time
}
func new(v string) userName {
return userName{
v, time.Now(),
}
}
func newWithCreationDate(v string, t time.Time) userName {
return userName{v, t}
}
package main
import (
"fmt"
)
type superHero struct {
name string
power string
}
func new(name, power string) superHero {
return superHero{name, power}
}
func (s superHero) action() {
fmt.Printf("the super hero %s uses %s", s.name, s.action)
}
func (s superHero) mutation(name, power string) superHero {
return new(name, power)
}
func main() {
superman := new("Superman", "laser eyes")
superman.action()
supermanRage := superman.mutation("Superman - rage mode", "super laser eyes")
superman.action()
supermanRage.action()
}
value receiver
package main
import "fmt"
type user struct {
id int
name string
}
func new(id int, name string) *user {
return &user{id, name}
}
func (u *user) rename(name string) {
u.name = name
}
func main() {
u := new(1, "Mario")
fmt.Println(u.name)
u.rename("Luigi")
fmt.Println(u.name)
}
pointer receiver
package main
import "fmt"
type user struct {
name string
}
type admin struct {
user
role string
}
func main() {
u := user{"Mario"}
a := admin{user{"Luigi"}, "CTO"}
fmt.Println(u.name)
fmt.Println(a.name, a.role)
}
package main
import "fmt"
type printer interface {
print(s string)
}
package main
import "fmt"
type printer interface {
print(s string)
}
type fmtPrinter struct {
}
func (p *fmtPrinter) print(s string) {
fmt.Println(s)
}
func main() {
p := &fmtPrinter{}
printerFunc("Mario", p)
}
func printerFunc(s string, p printer) {
p.print(s)
}
package main
import "fmt"
type printer interface {
print(s string)
}
type reader interface {
read(s string)
}
type printerReader interface {
printer
reader
}
type fmtPrinterReader struct {
s string
}
func (p *fmtPrinterReader) print(s string) {
fmt.Println(fmt.Sprintln(p.s, s))
}
func (p *fmtPrinterReader) read(s string) {
p.s = fmt.Sprintln(p.s, s)
}
func main() {
p := &fmtPrinterReader{}
printerFunc("Super", "Mario", p)
}
func printerFunc(read, print string, p printerReader) {
p.read(read)
p.print(print)
}
package main
import "fmt"
func main() {
printValue("Mario")
printValue(10)
printValue(struct{}{})
printValue(map[string]string{"Man": "Mario", "Woman": "Peach"})
}
func printValue(v interface{}) {
fmt.Println(v)
}
package main
type printer interface {
print(s string)
}
type fmtPrinter struct {
}
var _ printer = (*fmtPrinter)(nil)
// func (p *fmtPrinter) print(s string) {
// fmt.Println(s)
// }
package builtin
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
package main
import "errors"
var errUserNotFound = errors.New("main: user not found")
func main() {
var errUserNotFound = errors.New("main: user not found")
errUserNotLogged := errors.New("main: user not logged")
}
package main
import (
"errors"
"fmt"
"strconv"
)
func stringLength(s string) (int, error) {
i, err := strconv.Atoi(s)
if err != nil {
return 0, errors.New("main: an error occurred transforming string to integer")
}
return i, nil
}
// One-line idiomatic error check
func main() {
if _, err := stringLength("Mario"); err != nil {
fmt.Println(err)
return
}
fmt.Println("Job done!")
}
// Keep in mind the scope of the "if"
func main() {
i, err := stringLength("Mario")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(i)
}
package main
import (
"fmt"
"github.com/pkg/errors"
"strconv"
)
// Wrapping errors
func stringLength(s string) (int, error) {
i, err := strconv.Atoi(s)
if err != nil {
return 0, errors.Wrap(err, "main: an error occurred transforming string to integer")
}
return i, nil
}
func main() {
i, err := stringLength("Mario")
switch err := errors.Cause(err).(type) {
case *strconv.NumError:
fmt.Println(err)
default:
fmt.Println(i)
}
}
use carefully!
package main
import (
"fmt"
"github.com/pkg/errors"
"strconv"
)
func main() {
panic("ops!")
i, err := strconv.Atoi("Mario")
switch err := errors.Cause(err).(type) {
case *strconv.NumError:
fmt.Println(err)
default:
fmt.Println(i)
}
}
Do not use it! (or use it where it makes sense)
package main
import (
"fmt"
"github.com/pkg/errors"
"os"
"strconv"
)
func main() {
os.Exit(0)
i, err := strconv.Atoi("Mario")
switch err := errors.Cause(err).(type) {
case *strconv.NumError:
fmt.Println(err)
default:
fmt.Println(i)
}
}
A package is a bounded context.
All the structures and functions listed inside, are placed to solve a specific problem.
Use fewer chars as possible for naming
How to_name VARIABLES in-the-Code
A folder structure
Packages should not depend on other packages
initialize new module in current directory
add missing and remove unused modules
make vendored copy of dependencies
download modules to local cache