Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Shattered Mirror: An Introduction to Reflect and Unsafe

Shattered Mirror: An Introduction to Reflect and Unsafe

Go gives developers compile-time safety through its type system, and flexibility through interfaces. Sometimes, interfaces just aren’t flexible enough. Sometimes, you just want to write some code that isn’t safe at all. In this talk, you’ll learn about the outlaw packages of Go: reflect and unsafe. You’ll learn just enough about Go’s type system to understand how reflect and unsafe subvert it. Finally, you’ll see practical examples of using reflect, and some impractical examples of using unsafe.

James Bowes

March 25, 2019
Tweet

More Decks by James Bowes

Other Decks in Programming

Transcript

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

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

    w := rs.(io.Writer) var r io.Reader = w.(io.ReadWriter) " "
  3. 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
  4. func hello(msg string) { fmt.Println(msg) } func main() { f

    := reflect.ValueOf(hello) args := []reflect.Value{ reflect.ValueOf("hi!"), } f.Call(args) } @jrbowes
  5. 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
  6. 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
  7. @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
  8. @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
  9. type A struct { Name string } type B struct

    { Name, Value string } func main() { b := B{"a thing", "a value”} a := (*A)(&b) } @jrbowes
  10. 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
  11. package unsafe type ArbitraryType int type Pointer *ArbitraryType func Sizeof(x

    ArbitraryType) uintptr func Offsetof(x ArbitraryType) uintptr func Alignof(x ArbitraryType) uintptr @jrbowes