Slide 1

Slide 1 text

@jrbowes Shattered Mirror An introduction to reflect and unsafe

Slide 2

Slide 2 text

@jrbowes

Slide 3

Slide 3 text

@jrbowes

Slide 4

Slide 4 text

@jrbowes

Slide 5

Slide 5 text

@jrbowes

Slide 6

Slide 6 text

@jrbowes

Slide 7

Slide 7 text

You are already using reflect @jrbowes

Slide 8

Slide 8 text

import “encoding/json" @jrbowes

Slide 9

Slide 9 text

import “encoding/json" func Marshal(v interface{}) ([]byte, error) func Unmarshal(data []byte, v interface{}) error @jrbowes

Slide 10

Slide 10 text

type Response struct { Code int `json:"code"` Message string `json:"message"` } @jrbowes

Slide 11

Slide 11 text

You are already using reflect @jrbowes

Slide 12

Slide 12 text

You are already using reflect and unsafe @jrbowes

Slide 13

Slide 13 text

package main func main() { } @jrbowes

Slide 14

Slide 14 text

$> go list -f '{{.Deps}}' @jrbowes

Slide 15

Slide 15 text

$> go list -f '{{.Deps}}' [internal/bytealg internal/cpu runtime runtime/ internal/atomic runtime/internal/sys unsafe] @jrbowes

Slide 16

Slide 16 text

$> go list -f '{{.Deps}}' [internal/bytealg internal/cpu runtime runtime/ internal/atomic runtime/internal/sys unsafe] @jrbowes

Slide 17

Slide 17 text

It starts and ends with types @jrbowes

Slide 18

Slide 18 text

file, err := os.Open("data.txt") @jrbowes

Slide 19

Slide 19 text

file, err := os.Open("data.txt") @jrbowes

Slide 20

Slide 20 text

file, err := os.Open("data.txt") var rs io.ReadSeeker = file @jrbowes

Slide 21

Slide 21 text

file, err := os.Open("data.txt") var rs io.ReadSeeker = file @jrbowes

Slide 22

Slide 22 text

file, err := os.Open("data.txt") var rs io.ReadSeeker = file @jrbowes w := rs.(io.Writer)

Slide 23

Slide 23 text

file, err := os.Open("data.txt") var rs io.ReadSeeker = file @jrbowes w := rs.(io.Writer) "

Slide 24

Slide 24 text

file, err := os.Open("data.txt") var rs io.ReadSeeker = file @jrbowes w := rs.(io.Writer) var r io.Reader = w.(io.ReadWriter) "

Slide 25

Slide 25 text

file, err := os.Open("data.txt") var rs io.ReadSeeker = file @jrbowes w := rs.(io.Writer) var r io.Reader = w.(io.ReadWriter) " "

Slide 26

Slide 26 text

@jrbowes os.Open("data.txt")

Slide 27

Slide 27 text

@jrbowes os.Open("data.txt") type File struct {}

Slide 28

Slide 28 text

@jrbowes os.Open("data.txt") type File struct {} type Writer interface {}

Slide 29

Slide 29 text

The Go runtime needs your type information @jrbowes

Slide 30

Slide 30 text

The Go runtime needs your type information …mostly @jrbowes

Slide 31

Slide 31 text

reflect @jrbowes

Slide 32

Slide 32 text

func ValueOf(i interface{}) Value func TypeOf(i interface{}) Type @jrbowes

Slide 33

Slide 33 text

oneThing := another @jrbowes

Slide 34

Slide 34 text

func main() { c := make(chan bool) go func() { v := reflect.ValueOf(c) b := reflect.Zero(v.Type().Elem()) v.Send(b) v.Close() }() for range c { fmt.Println("saw value”) } } @jrbowes

Slide 35

Slide 35 text

func hello(msg string) { fmt.Println(msg) } func main() { f := reflect.ValueOf(hello) args := []reflect.Value{ reflect.ValueOf("hi!"), } f.Call(args) } @jrbowes

Slide 36

Slide 36 text

type A struct { Name string Value string `rename:"val"` } func main() { a := A{Name: "a name", Value: "a value"} v := reflect.ValueOf(a) vt := v.Type() for i := 0; i < v.NumField(); i++ { f := vt.Field(i) name := f.Name if t, ok := f.Tag.Lookup("rename"); ok { name = t } fmt.Printf("%s: %s\n", name, v.Field(i)) } } @jrbowes

Slide 37

Slide 37 text

func main() { st := reflect.StructOf([]reflect.StructField{{ Name: "Message", Type: reflect.TypeOf(""), Tag: `json:"msg"`, }}) s := reflect.New(st) s.Elem().FieldByName("Message").Set(reflect.ValueOf("hi!")) i := s.Interface() o, _ := json.Marshal(i) fmt.Println(string(o)) } @jrbowes

Slide 38

Slide 38 text

@jrbowes

Slide 39

Slide 39 text

@jrbowes

Slide 40

Slide 40 text

@jrbowes reflect.ValueOf() reflect.MakeFunc()

Slide 41

Slide 41 text

unsafe @jrbowes

Slide 42

Slide 42 text

@jrbowes file, err := os.Open(“data.txt”) var rs io.ReadSeeker = file w := rs.(io.Writer) " var r io.Reader = w.(io.ReadWriter) " type Writer interface {} type File struct {} os.Open(“data.txt") oneThing := another

Slide 43

Slide 43 text

@jrbowes file, err := os.Open(“data.txt”) var rs io.ReadSeeker = file w := rs.(io.Writer) " var r io.Reader = w.(io.ReadWriter) " type Writer interface {} type File struct {} os.Open(“data.txt") oneThing := another

Slide 44

Slide 44 text

type A struct { Name string } type B struct { Name, Value string } func main() { b := B{"a thing", "a value”} a := (*A)(&b) } @jrbowes

Slide 45

Slide 45 text

type A struct { Name string } type B struct { Name, Value string } func main() { b := B{"a thing", "a value"} a := (*A)(unsafe.Pointer(&b)) } @jrbowes

Slide 46

Slide 46 text

func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) @jrbowes

Slide 47

Slide 47 text

reflect @jrbowes

Slide 48

Slide 48 text

reflect @jrbowes needs unsafe

Slide 49

Slide 49 text

package unsafe type ArbitraryType int type Pointer *ArbitraryType func Sizeof(x ArbitraryType) uintptr func Offsetof(x ArbitraryType) uintptr func Alignof(x ArbitraryType) uintptr @jrbowes

Slide 50

Slide 50 text

@jrbowes

Slide 51

Slide 51 text

@jrbowes

Slide 52

Slide 52 text

@jrbowes func billingState( ctx context.Context, billing *client.Billing, op *Operation ) (string, error) next, err := step()

Slide 53

Slide 53 text

@jrbowes func billingState( ctx context.Context, billing *client.Billing, op *Operation ) (string, error) next, err := step()

Slide 54

Slide 54 text

@jrbowes func billingState( ctx context.Context, billing *client.Billing, op *Operation ) (string, error) next, err := step()

Slide 55

Slide 55 text

@jrbowes func billingState( ctx context.Context, billing *client.Billing, op *Operation ) (string, error) next, err := step()

Slide 56

Slide 56 text

Don’t use reflect for runtime dependency injection @jrbowes

Slide 57

Slide 57 text

Keep the flow of control in one direction @jrbowes

Slide 58

Slide 58 text

reflect is best for reading @jrbowes

Slide 59

Slide 59 text

reflect is good for writing data @jrbowes

Slide 60

Slide 60 text

Don’t use unsafe directly ;) @jrbowes

Slide 61

Slide 61 text

FIND ME github.com/jbowes twitter.com/jrbowes manifold.co Thank you! @jrbowes