$ go please
go please: unknown command
Run 'go help' for usage.
What you thought about Go
Or maybe
How it actually felt
func double(s []int) []int {
b := s
for i, v := range b {
b[i] = 2 * v
}
return b
}
func main() {
a := []int{3, 5, 8}
b := double(a)
fmt.Println(a)
fmt.Println(b)
}
"A Slice of Betrayal"
func double(s []int) []int {
b := s
for i, v := range b {
b[i] = 2 * v
}
return b
}
func main() {
a := []int{3, 5, 8}
b := double(a)
fmt.Println(a)
fmt.Println(b)
}
// >> [6 10 16]
// >> [6 10 16]
"A Slice of Betrayal"
"A Slice of Betrayal"
func double(s []int) []int {
b := make([]int, len(s))
copy(b, s)
for i, v := range b {
b[i] = 2 * v
}
return b
}
func main() {
a := []int{3, 5, 8}
b := double(a)
fmt.Println(a)
fmt.Println(b)
}
// >> [3 5 8]
// >> [6 10 16]
"A Slice of Betrayal"
func main() {
x := make([]int, 5)
for i := range x {
x = append(x, i)
}
fmt.Println(x, cap(x), len(x))
}
"The Pit and the Append-ulum"
func main() {
x := make([]int, 5)
for i := range x {
x = append(x, i)
}
fmt.Println(x, cap(x), len(x))
}
// >> [0 0 0 0 0 0 1 2 3 4] 10 10
"The Pit and the Append-ulum"
func main() {
x := make([]int, 0, 5)
for i := 0; i < 5; i++ {
x = append(x, i)
}
fmt.Println(x, cap(x), len(x))
}
// >> [0 1 2 3 4] 5 5
"The Pit and the Append-ulum"
func main() {
x := []int{}
for i := 0; i < 5; i++ {
x = append(x, i)
}
fmt.Println(x, cap(x), len(x))
}
// >> [0 1 2 3 4] 8 5
"The Pit and the Append-ulum"
func loadOne(c config) error {
return errors.New("load one failed: bad config")
}
func initialize(typ string) (err error) {
switch typ {
case "one":
x, err := getOneConfig()
if err != nil {
fmt.Println(err)
}
err = loadOne(x)
case "two":
err = loadTwo()
}
return
}
func main() {
fmt.Println(initialize("one"))
}
"Shadows in the Dark"
func initialize(typ string) (err error) {
switch typ {
case "one":
x, err := getOneConfig()
if err != nil {
fmt.Println(err)
}
err = loadOne(x)
case "two":
err = loadTwo()
}
return
}
func main() {
fmt.Println(initialize("one"))
}
// >> <nil>
"Shadows in the Dark"
func initialize(typ string) (err error) {
switch typ {
case "one":
var x oneConfig
x, err = getOneConfig()
if err != nil {
fmt.Println(err)
}
err = loadOne(x)
case "two":
err = loadTwo()
}
return err
}
func main() {
fmt.Println(initialize("one"))
}
// >> load one failed: bad config
"Shadows in the Dark"
"Shadows in the Dark"
go vet -shadow
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)
type ErrEx struct{}
func (*ErrEx) Error() string {
return "failed"
}
func execute() *ErrEx {
return nil
}
func main() {
var err error
err = execute()
if err != nil {
fmt.Println("😱")
} else {
fmt.Println("😎")
}
}
"To Err is Human"
type ErrEx struct{}
func (*ErrEx) Error() string {
return "failed"
}
func execute() *ErrEx {
return nil
}
func main() {
var err error
err = execute()
if err != nil {
fmt.Println("😱")
} else {
fmt.Println("😎")
}
}
// >> 😱
"To Err is Human"
"To Err is Human"
type ErrEx struct{}
func (*ErrEx) Error() string {
return "failed"
}
func execute() error {
return nil
}
func main() {
var err error
err = execute()
if err != nil {
fmt.Println("😱")
} else {
fmt.Println("😎")
}
}
// >> 😎
"To Err is Human"
func main() {
for i := 0; i < 5; i++ {
go func() {
fmt.Println(i)
}()
}
}
"Merry Go Round"
func main() {
for i := 0; i < 5; i++ {
go func() {
fmt.Println(i)
}()
}
}
// >>
// echo $?
// >> 0
"Merry Go Round"
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
}
"Merry Go Round"
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
}
// >> 5
// >> 5
// >> 5
// >> 5
// >> 5
"Merry Go Round"
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(local int) {
fmt.Println(local)
wg.Done()
}(i)
}
wg.Wait()
}
// >> 4
// >> 0
// >> 2
// >> 1
// >> 3
"Merry Go Round"
func theLongNight() (ret string) {
defer func() {
fmt.Println(ret)
ret = "🦌"
}()
defer func() {
fmt.Println(ret)
ret = "🐺"
}()
ret = "🐲"
return "🦁"
}
func main() {
fmt.Println(theLongNight())
}
"Game of Throws"
func theLongNight() (ret string) {
defer func() {
fmt.Println(ret)
ret = "🦌"
}()
defer func() {
fmt.Println(ret)
ret = "🐺"
}()
ret = "🐲"
return "🦁"
}
func main() {
fmt.Println(theLongNight())
}
// >> 🦁
// >> 🐺
// >> 🦌
"Game of Throws"
type Vampire struct {
name string `json:"name"`
age int `json:"age"`
}
func main() {
d := json.NewDecoder(os.Stdin)
var vamps Vampire
err := d.Decode(&vamps)
if err != nil {
fmt.Println("😱")
}
fmt.Println(vamps)
}
"Shifty Serialization"
type Vampire struct {
name string `json:"name"`
age int `json:"age"`
}
func main() {
d := json.NewDecoder(os.Stdin)
var vamps Vampire
err := d.Decode(&vamps)
if err != nil {
fmt.Println("😱")
}
fmt.Printf("%+v\n", vamps)
}
// << {"name": "Dracula", "age": 102}
// >> {name: age:0}
"Shifty Serialization"
type Vampire struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
d := json.NewDecoder(os.Stdin)
var vamps Vampire
err := d.Decode(&vamps)
if err != nil {
fmt.Println("😱")
}
fmt.Printf("%+v\n", vamps)
}
// << {"name": "Dracula", "age": 102}
// >> {Name:Dracula Age:102}
"Shifty Serialization"
type ConnWrapper struct {
conn string
}
func (cw ConnWrapper) Wrap(c string) {
cw.conn = c
}
func (cw ConnWrapper) Read() string {
return cw.conn
}
func main() {
cw := ConnWrapper{"initial-host:80"}
cw.Wrap("redirect-host:8080")
fmt.Println(cw.Read())
}
"Value Receiver"
type ConnWrapper struct {
conn string
}
func (cw ConnWrapper) Wrap(c string) {
cw.conn = c
}
func (cw ConnWrapper) Read() string {
return cw.conn
}
func main() {
cw := ConnWrapper{"initial-host:80"}
cw.Wrap("redirect-host:8080")
fmt.Println(cw.Read())
}
// >> initial-host:80
"Value Receiver"
type ConnWrapper struct {
conn string
}
func (cw *ConnWrapper) Wrap(c string) {
cw.conn = c
}
func (cw *ConnWrapper) Read() string {
return cw.conn
}
func main() {
cw := ConnWrapper{"initial-host:80"}
cw.Wrap("redirect-host:8080")
fmt.Println(cw.Read())
}
// >> redirect-host:8080
"Pointer Receiver"
func main() {
var cache map[string]string
x := cache["0xdeadbeef"]
fmt.Println(x)
cache["0x5ca1ab1e"] = "webscale"
fmt.Println(cache)
}
"Treasure Map"
func main() {
var cache map[string]string
x := cache["0xdeadbeef"]
fmt.Println(x)
cache["0x5ca1ab1e"] = "webscale"
fmt.Println(cache)
}
// >> panic: assignment to entry in nil map
// >>
// >> goroutine 1 [running]:
// >> main.main()
// >> map_initialization.go:9 +0xf8
// >> exit status 2
"Treasure Map"
func main() {
cache := map[string]string{}
x := cache["0xdeadbeef"]
fmt.Println(x)
cache["0x5ca1ab1e"] = "webscale"
fmt.Println(cache)
}
func main() {
cache := make(map[string]string)
x := cache["0xdeadbeef"]
fmt.Println(x)
cache["0x5ca1ab1e"] = "webscale"
fmt.Println(cache)
}
// >>
// >> map[0x5ca1ab1e:webscale]
"Treasure Map"
var cache = make(map[string]string)
func get(w http.ResponseWriter, r *http.Request) {
k := r.URL.Query().Get("key")
w.Write([]byte(cache[k]))
}
func set(w http.ResponseWriter, r *http.Request) {
k := r.URL.Query().Get("key")
v := r.URL.Query().Get("val")
cache[k] = v
}
func main() {
http.HandleFunc("/set", set)
http.HandleFunc("/get", get)
http.ListenAndServe(":8080", nil)
}
"Concurrent Treasure Map"
var cache = make(map[string]string)
var lock = sync.RWMutex{}
func get(w http.ResponseWriter, r *http.Request) {
k := r.URL.Query().Get("key")
lock.RLock()
w.Write([]byte(cache[k]))
lock.RUnlock()
}
func set(w http.ResponseWriter, r *http.Request) {
k := r.URL.Query().Get("key")
v := r.URL.Query().Get("val")
lock.Lock()
cache[k] = v
lock.Unlock()
}
"Concurrent Treasure Map"
func main() {
b := make(chan struct{})
b <- struct{}{}
<-b
fmt.Println("okay")
}
"Think you're buff?"
func main() {
b := make(chan struct{})
b <- struct{}{}
<-b
fmt.Println("okay")
}
// >> fatal error: all goroutines are asleep - deadlock!
// >>
// >> goroutine 1 [chan send]:
// >> main.main()
// >> chan_unbuf.go:7 +0x57
// >> exit status 2
"Think you're buff?"
func main() {
b := make(chan struct{}, 1)
b <- struct{}{}
<-b
fmt.Println("okay")
}
"Think you're buff?"
func main() {
b := make(chan struct{}, 1)
b <- struct{}{}
<-b
fmt.Println("okay")
}
// >> okay
"Think you're buff?"
func main() {
x := make(chan int, 1)
y := make(chan int, 1)
z := make(chan int, 1)
x <- 1
y <- 2
z <- 3
select {
case <-x:
fmt.Println("read x")
case <-y:
fmt.Println("read y")
case <-z:
fmt.Println("read z")
}
}
"Select *"
func main() {
x := make(chan int, 1)
y := make(chan int, 1)
z := make(chan int, 1)
x <- 1
y <- 2
z <- 3
select {
case <-x:
fmt.Println("read x")
case <-y:
fmt.Println("read y")
case <-z:
fmt.Println("read z")
}
}
// >> read y
"Select *"
func main() {
x := make(chan int, 1)
y := make(chan int, 1)
z := make(chan int, 1)
x <- 1
y <- 2
z <- 3
select {
case <-x:
fmt.Println("read x")
case <-y:
fmt.Println("read y")
case <-z:
fmt.Println("read z")
}
}
// >> read y
// >> read z
"Select *"
func main() {
x := make(chan int, 1)
y := make(chan int, 1)
z := make(chan int, 1)
x <- 1
y <- 2
z <- 3
select {
case <-x:
fmt.Println("read x")
case <-y:
fmt.Println("read y")
case <-z:
fmt.Println("read z")
}
}
// >> read y
// >> read z
// >> read y
"Select *"
func main() {
x := make(chan int)
go func() {
x <- 1
}()
select {
case <-x:
fmt.Println("read x")
default:
fmt.Println("default")
}
}
"Select *"
func main() {
x := make(chan int)
go func() {
x <- 1
}()
select {
case <-x:
fmt.Println("read x")
default:
fmt.Println("default")
}
}
// >> default
"Select *"
func main() {
x := make(chan int)
go func() {
x <- 1
}()
select {
case <-x:
fmt.Println("read x")
default:
fmt.Println("default")
}
}
// >> default
// >> default
"Select *"
func main() {
x := make(chan int)
go func() {
x <- 1
}()
select {
case <-x:
fmt.Println("read x")
default:
fmt.Println("default")
}
}
// >> default
// >> default
// >> default
"Select *"
func main() {
x := make(chan int)
go func() {
x <- 1
}()
time.Sleep(10*time.Millisecond)
select {
case <-x:
fmt.Println("read x")
default:
fmt.Println("default")
}
}
// >> read x
"Select *"
func main() {
x := make(chan int)
go func() {
x <- 1
}()
time.Sleep(10*time.Millisecond)
select {
case <-x:
fmt.Println("read x")
default:
fmt.Println("default")
}
}
// >> read x
// >> read x
"Select *"
"Select *"
- Vet your code
- Test your code
- See weird behavior?
- Look to the spec
- Ask in #golang
go please
By Alan Braithwaite
go please
- 1,176