How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016
-
Upload
codemotion -
Category
Technology
-
view
51 -
download
2
Transcript of How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016
![Page 1: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/1.jpg)
How to avoid Go gotchasby learning internals
Ivan Danyliuk, Codemotion Milano 26 Nov 2016
![Page 2: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/2.jpg)
Gotchas• Go has some gotchas
• Good examples:
• 50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs
• Go Traps
• Golang slice append gotcha
![Page 3: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/3.jpg)
Gotchas• Luckily, Go has very few gotchas
• Especially in comparison with other languages
Go
C++
0 75 150 225 300
![Page 4: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/4.jpg)
Gotchas
• So, what is gotcha?
• “a gotcha is a valid construct in a system, program or programming language that works as documented but is counter-intuitive and almost invites mistakes because it is both easy to invoke and unexpected or unreasonable in its outcome”
![Page 5: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/5.jpg)
Gotchas
• Two solutions:
• “fix” the language
• fix the intuition.
• Let’s build some intuition to fight gotchas then.
![Page 6: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/6.jpg)
Gotchas
• Let’s learn some internals and in memory representations
• It worked for me, should work for you as well.
![Page 7: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/7.jpg)
basic typesCode:
i := 1234 j := int32(4) i64 := int64(999) f := float32(3.14)
![Page 8: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/8.jpg)
Code:
i := 1234 j := int32(4) i64 := int64(999) f := float32(3.14)
1234
i
4
j
3.14
fi64
999
int int32
float32int64
basic types
![Page 9: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/9.jpg)
structsCode:
type Point struct { X, Y int }
p1 := Point{10, 20}
10
int
20
int
p1
![Page 10: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/10.jpg)
Code:
type Point struct { X, Y int }
p1 := Point{10, 20} p2 := &Point{10, 20}
10
int
20
int
p1
10
int
20
int
p2
0x..
*Point
basic types
![Page 11: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/11.jpg)
structsCode:
func Foo(p Point) { // ... }
p1 := Point{10, 20} Foo(p1)
10
int
20
int
p1
10
int
20
int
Foo() copy
![Page 12: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/12.jpg)
structsCode:
func Foo(p *Point) { // ... }
p2 := &Point{10, 20} Foo(p2)
Foo()
copy 10
int
20
int
p2
0x..
*Point
0x..
![Page 13: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/13.jpg)
array
var arr [5]intCode:
![Page 14: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/14.jpg)
array
var arr [5]int
Go code: src/runtime/malloc.go// newarray allocates an array of n elements of type typ. func newarray(typ *_type, n int) unsafe.Pointer { if n < 0 || uintptr(n) > maxSliceCap(typ.size) { panic(plainError("runtime: allocation size out of range")) } return mallocgc(typ.size*uintptr(n), typ, true) }
Code:
![Page 15: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/15.jpg)
array
var arr [5]intCode:
int
Memory:
![Page 16: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/16.jpg)
array
var arr [5]intCode: 4 or 8 bytes blocks
(32 or 64 bit arch)
int
Memory:
![Page 17: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/17.jpg)
array
var arr [5]intCode:
int0 1 2 3 4
Memory:
![Page 18: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/18.jpg)
array
var arr [5]intCode:
int0 1 2 3 4
0 0 0 0 0Memory:
![Page 19: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/19.jpg)
arrayCode:
Memory:
int0 1 2 3 4
0 0 0 0 42
var arr [5]int arr[4] = 42
![Page 20: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/20.jpg)
slice
var foo []intCode:
![Page 21: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/21.jpg)
slice
var foo []intCode:
Go code: src/runtime/slice.gotype slice struct { array unsafe.Pointer len int cap int }
![Page 22: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/22.jpg)
slice
var foo []intCode:
Go code: src/runtime/slice.go
array
len
cap
0 1 2 3 4
foo
type slice struct { array unsafe.Pointer len int cap int }
![Page 23: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/23.jpg)
sliceCode:
array
len
cap
0 1 2 3 4
nil
0
0
var foo []intfoo
![Page 24: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/24.jpg)
slice
var foo []int foo = make([]int, 5)
Code:
array
len
cap
000 0 00x..
5
50 1 2 3 40 1 2 3 4
foo
![Page 25: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/25.jpg)
slice
var foo []int foo = make([]int, 3, 5)
Code:
array
len
cap
00 00x..
3
50 1 2 3 40 1 2 3 4
foo
![Page 26: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/26.jpg)
slice
var foo []int foo = make([]int, 5) foo[3] = 42 foo[4] = 100
Code:
array
len
cap
4200 0 1000 1 2 3 4
0x..
5
50 1 2 3 40 1 2 3 4
foo
![Page 27: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/27.jpg)
sliceCode:
array
len
cap
0x..
5
5
var foo []int foo = make([]int, 5) foo[3] = 42 foo[4] = 100
bar := foo[1:4]
4200 0 1000 1 2 3 40 1 2 3 40 1 2 3 4
foo
![Page 28: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/28.jpg)
sliceCode:
array
len
cap
4200 0 100
0
1 2 3 40x..
5
50
1 2 3 40 1 2 3 4
var foo []int foo = make([]int, 5) foo[3] = 42 foo[4] = 100
bar := foo[1:4] array
len
cap
bar
0x..
3
3
foo
![Page 29: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/29.jpg)
sliceCode:
array
len
cap
42990 0 100
0
1 2 3 4
foo
0x..
5
50
1 2 3 40 1 2 3 4
var foo []int foo = make([]int, 5) foo[3] = 42 foo[4] = 100
bar := foo[1:4] bar[1] = 99
array
len
cap
bar
0x..
3
3
0 1 2
![Page 30: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/30.jpg)
sliceCode:
var digitRegexp = regexp.MustCompile("[0-9]+")
func FindDigits(filename string) []byte { b, _ := ioutil.ReadFile(filename) return digitRegexp.Find(b) }
![Page 31: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/31.jpg)
slice
array
len
cap
32r 1 $
0
b
0x..
10^6 0
array
len
cap
digitRegexp.Find
0x..
3
3
10^6
xa b c d …
10MB slice
![Page 32: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/32.jpg)
appendCode:
a := make([]int, 32) a = append(a, 1)
![Page 33: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/33.jpg)
appendCode:
a := make([]int, 32) a = append(a, 1) fmt.Println("len:", len(b), "cap:", cap(b))
len: 33 cap: 64Output:
![Page 34: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/34.jpg)
append
array
len
cap
000 0 0a
0x..
32
32
0 1 2 3 40 1 2 30 31
…
32 ints
a = append(a, 1)
![Page 35: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/35.jpg)
array
len
cap
000 0 0
a
0x..
33
640 1 2 3 40 1 2 30 31
… 132 33 34
…35 62 63
32 ints more
32 + 1
doubling 32
000 0 00 1 2 3 40 1 2 30 31
…
32 ints
![Page 36: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/36.jpg)
append
array
len
cap
000 0 0
a
0x..
34
640 1 2 3 40 1 2 30 31
… 1 232 33 34
…35 62 63
33 + 1 a = append(a, 2)
64 ints
![Page 37: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/37.jpg)
interfacesCode:
type error interface { Error() string }
![Page 38: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/38.jpg)
interfacesCode:
Go code: src/runtime/runtime2.go
type iface struct { tab *itab data unsafe.Pointer }
type error interface { Error() string }
![Page 39: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/39.jpg)
type iface struct { tab *itab data unsafe.Pointer }
type error interface { Error() string }
interfacesCode:
Go code: src/runtime/runtime2.go itab = interface table
![Page 40: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/40.jpg)
type iface struct { tab *itab data unsafe.Pointer }
type error interface { Error() string }
interfacesCode:
Go code: src/runtime/runtime2.go
type itab struct { inter *interfacetype _type *_type link *itab bad int32 unused int32 fun [1]uintptr }
![Page 41: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/41.jpg)
interfacesCode:
tab
data
type error interface { Error() string }
![Page 42: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/42.jpg)
data
tab
nil
0x..
interfacesCode:
inter
type
nil
error
fun
itab
…
type error interface { Error() string }
var err error
err
nil interface
![Page 43: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/43.jpg)
interfacesCode:
type error interface { Error() string }
func foo() error { return nil }
data
tab
nil
0x..inter
type
nil
error
fun
itab
…
err
![Page 44: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/44.jpg)
interfacesCode:
data
tab
nil
0x..inter
type
nil
error
fun
itab
…
errfunc foo() error { var err error // err == nil return err }
err := foo() if err != nil { // false }
![Page 45: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/45.jpg)
interfaces
func foo() error { var err *os.PathError // err == nil return err }
err := foo() if err != nil { // ??? }
Code:
![Page 46: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/46.jpg)
interfaces
func foo() error { var err *os.PathError // err == nil return err }
err := foo() if err != nil { // true }
Code:
![Page 47: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/47.jpg)
interfaces
func foo() error { var err *os.PathError // err == nil return err }
err := foo() if err != nil { // true }
Code:
tab0x..
inter
type
*os.PathError
error
fun
itab
…
err
data
os.PathError
err
nil
0x..
![Page 48: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/48.jpg)
tab
interfaces
func foo() error { err := &os.PathError{ "open", name, e } return err }
err := foo() if err != nil { // true }
Code:
data0x..
0x..inter
type
*os.PathError
error
fun
itab
…
err
os.PathError
err“open”
…
![Page 49: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/49.jpg)
interfaces
func foo() error { var err *os.PathError // err == nil return err }
func foo() error { var err error // err == nil return err }
data
tab
nil
0x..inter
typenil
error
fun
itab
…
err
data
tab0x..
inter
type
*os.PathError
error
fun
itab
…
err
0x..
os.PathError
nil
err
![Page 50: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/50.jpg)
interfaces
tab0x..
inter
type
*os.PathError
error
fun
itab
…
err
data
os.PathError
err
nil
0x..data
tab
nil
0x..inter
type
nil
error
fun
itab
…
err
!=
![Page 51: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/51.jpg)
type eface struct { _type *_type data unsafe.Pointer }
type empty interface{}
interfacesCode:
Go code: src/runtime/runtime2.go
_type
data
![Page 52: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/52.jpg)
interfaces
int64
0x..
int64
42
empty
foo
var foo int64 = 42
func bar() interface{} { return foo }
Code:
![Page 53: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/53.jpg)
interfaces
func bar() interface{} { return int64(42) }
Code:
![Page 54: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/54.jpg)
interfaces
func bar() []interface{} { return []int64{1,2,3,4} }
Code:
![Page 55: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/55.jpg)
interfaces
func bar() []interface{} { return []int64{1,2,3,4} }
Code:
$ go build cannot use []int literal (type []int) as type []interface {} in return argument
![Page 56: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/56.jpg)
array
len
cap
[]int
0x..
32
32
4
3131 2 320 1 2 30 1 2 30 31
…
32 ints
array
len
cap
0x..
32
32
0…
32 interfaces{}[]interface{}
int
0x..
int
1
empty
data
int
0x..
int
2
empty
data
int
0x..
int3
empty
data
0int
0x..
int
31
empty
data
int
0x..
int
32
empty
data
![Page 57: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/57.jpg)
If you want to do something expensive - do it explicitly
![Page 59: How to avoid Go gotchas - Ivan Daniluk - Codemotion Milan 2016](https://reader033.fdocuments.us/reader033/viewer/2022042907/587080bb1a28ab57368b650f/html5/thumbnails/59.jpg)
Links• Must read:
• Go Data Structures
• Go Data Structures: Interfaces
• Go Slices: usage and internals
• Gopher Puzzlers
• And, of course:
• Go source code
• Effective Go
• Go spec