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

Impossible Go - GopherCon UK 2019

Impossible Go - GopherCon UK 2019

You know how to code in Go, don’t you? Let’s see!

This talk shows Go snippets that seem easy, difficult, wrong or impossible. Through these different Go constructs and code, we not only have fun but also learn about various nuances of Go to improve our Go coding skills and practices!

Of course, with some humour and life's learnings :P

Avatar for Gautam Rege

Gautam Rege

August 22, 2019
Tweet

Other Decks in Programming

Transcript

  1. What to expect from this talk! • Test your Go

    language skills • Code snippet teasers! • Run actual code with “impossible?” results! • Peek under the language hood to improve your Language concepts and programming practices to become a better programmer! • Earn some goodies when questions are thrown open to you! • Confessions of an Entrepreneur!
  2. Content Sources • Mistakes and goof-ups, unexpected code behaviour •

    WTF moments. • Anuj Verma - co-author of this talk GoLang Doc specifications are precise “there always a deeper meaning”
  3. Slice Array Wars Slice : [ 4, 5, 6 ]

    Array: [ 1, 2, 3, 4, 5, 6, 7, 8 ] arr := [8]int{1, 2, 3, 4, 5, 6, 7, 8} s := arr[3:6]
  4. Slice Array Wars Slice : [ 4, 5, 6 ]

    Array: [ 1, 2, 3, 4, 5, 6, 7, 8 ] arr := [8]int{1, 2, 3, 4, 5, 6, 7, 8} s := arr[3:6] s[2] = 10
  5. Slice Array Wars Slice : [ 4, 5, 10 ]

    Array: [ 1, 2, 3, 4, 5, 10, 7, 8 ] arr := [8]int{1, 2, 3, 4, 5, 6, 7, 8} s := arr[3:6] s[2] = 10
  6. Slice : [ 4, 5, 10 ] Array: [ 1,

    2, 3, 4, 5, 10, 7, 8 ] Slice Array Wars arr := [8]int{1, 2, 3, 4, 5, 6, 7, 8} s := arr[3:6] s[2] = 10 s = append(s, 11)
  7. Slice Array Wars Slice : [ 4, 5, 10, 11

    ] Array: [ 1, 2, 3, 4, 5, 10, 11, 8 ] arr := [8]int{1, 2, 3, 4, 5, 6, 7, 8} s := arr[3:6] s[2] = 10 s = append(s, 11)
  8. Slice Array Wars arr := [8]int{1, 2, 3, 4, 5,

    6, 7, 8} s := arr[3:6] s[2] = 10 s = append(s, 11) s = append(s, []int{12, 13, 14}…) Slice : [ 4, 5, 10, 11 ] Array: [ 1, 2, 3, 4, 5, 10, 11, 8 ]
  9. Slice Array Wars arr := [8]int{1, 2, 3, 4, 5,

    6, 7, 8} s := arr[3:6] s[2] = 10 s = append(s, 11) s = append(s, []int{12, 13, 14}...) Slice : [ 4, 5, 10, 11, 12, 13, 14 ] Array: [ 1, 2, 3, 4, 5, 10, 11, 8 ]
  10. Slice Array Wars 8 8 ptr 1 2 3 4

    5 6 7 8 Array Len Cap 3 5 ptr Slice Len Cap 0 1 2 3 4 s := arr[3:6]
  11. Slice Array Wars 8 8 ptr 1 2 3 4

    5 10 7 8 Array Len Cap 3 5 ptr Slice Len Cap s[2] = 10 0 1 2 3 4
  12. Slice Array Wars 8 8 ptr 1 2 3 4

    5 10 11 8 Array Len Cap 4 5 ptr Slice Len Cap s = append(s, 11) 0 1 2 3 4
  13. Slice Array Wars 8 8 ptr 1 2 3 4

    5 10 11 8 Array Len Cap 7 10 ptr Slice Len Cap s = append(s, []int{12, 13, 14}...) 4 5 10 11 12 13 14
  14. David & Goliath 2 Programmers Accounting Management Sales Marketing Funds

    Domain Expertise Contacts 2007 1 https://flic.kr/p/5jvooN
  15. David & Goliath 2 Programmers Accounting Management Sales Marketing Funds

    Domain Expertise Contacts 2007 1 https://flic.kr/p/5jvooN
  16. David & Goliath 2 Programmers Accounting Management Sales Marketing Funds

    Domain Expertise Contacts 2007 1 https://flic.kr/p/5jvooN
  17. David & Goliath 2 Programmers Accounting Management Sales Marketing Funds

    Domain Expertise Contacts 2007 1 https://flic.kr/p/5jvooN
  18. David & Goliath 2 Programmers Accounting Management Sales Marketing Funds

    Domain Expertise Contacts Passion 2007 1 https://flic.kr/p/5jvooN
  19. Comparisons type MyInt int var a int = 12 b

    := MyInt(12) fmt.Println(a == b)
  20. Comparisons type MyInt int var a int = 12 b

    := MyInt(12) fmt.Println(a == b) invalid operation: a == b (mismatched types int and MyInt)
  21. Comparisons type Foo struct { Name string Age int nickName

    string realAge int } fakeFoo := struct { Name string Age int nickName string realAge int }{"Gautam", 18, "Boss", 40} realFoo := Foo{"Gautam", 18, "Boss", 40} fmt.Println(fakeFoo == realFoo)
  22. Comparisons type Foo struct { Name string Age int nickName

    string realAge int } fakeFoo := struct { Name string Age int nickName string realAge int }{"Gautam", 18, "Boss", 40} realFoo := Foo{"Gautam", 18, "Boss", 40} fmt.Println(fakeFoo == realFoo) true
  23. Comparisons type Foo struct { Name string Age int nickName

    string realAge int } fakeFoo := struct { Name string Age int nickName string realAge int }{"Gautam", 18, "Boss", 40} realFoo := Foo{"Gautam", 18, "Boss", 40} compareStruct(fakeFoo, realFoo) func compareStruct(a, b interface{}) { fmt.Println(a == b) }
  24. Comparisons type Foo struct { Name string Age int nickName

    string realAge int } fakeFoo := struct { Name string Age int nickName string realAge int }{"Gautam", 18, "Boss", 40} realFoo := Foo{"Gautam", 18, "Boss", 40} compareStruct(fakeFoo, realFoo) func compareStruct(a, b interface{}) { fmt.Println(a == b) }
  25. Comparisons type Foo struct { Name string Age int nickName

    string realAge int } fakeFoo := struct { Name string Age int nickName string realAge int }{"Gautam", 18, "Boss", 40} realFoo := Foo{"Gautam", 18, "Boss", 40} compareStruct(fakeFoo, realFoo) func compareStruct(a, b interface{}) { fmt.Println(a == b) } false
  26. Comparisons type Foo struct { Name string Age int nickName

    string // what's the magic here ??? realAge int } foo := Foo{"Gautam", 18, “Boss", "phew", 40} phoo := Foo{"Gautam", 18, "Boss","tchoo", 40} fmt.Println(foo == phoo) true
  27. Comparisons type Foo struct { Name string Age int nickName

    string _ string realAge int } foo := Foo{"Gautam", 18, “Boss", "phew", 40} phoo := Foo{"Gautam", 18, "Boss","tchoo", 40} fmt.Println(foo == phoo) true
  28. Comparisons s1 := []int{1, 2, 3} s2 := []int{1, 2,

    3} fmt.Println(s1 == s2) invalid operation: s1 == s2 (slice can only be compared to nil)
  29. Comparison Rules • Rule #1: Types are same (except for

    struct where fields are compared) AND • Rule #2: Values are identical (non-blank fields in struct are ignored) Maps, slices and functions are pointers: No de-referencing Only Interface{} will check dynamic type
  30. Iterating Maps func main() { tickets := map[int]string{ 101: "Gautam",

    102: "John", 103: "Jane", 104: "Doe", 105: "Jeremy", 106: "Adam", 107: "Jack", 108: "Zoe", 201: "Regies", 202: "Anuj", 203: "Jake", 204: "Ivy", 205: "Anusha", 206: "Adam", 207: "Will", 208: "Eva", } for k, v := range tickets { fmt.Println(k, v) } }
  31. Impossible? p1, err := NewPerson(name, age) if err != nil

    { fmt.Println("Person not born!") } p4, err := NewPerson(name, age, weight, height) if err != nil { fmt.Println("Person not born!") }
  32. Impossible? p1, err := NewPerson(name, age) if err != nil

    { fmt.Println("Person not born!") } p4, err := NewPerson(name, age, weight, height) if err != nil { fmt.Println("Person not born!") }
  33. Functional Options type option func(*Server) func tls(val bool) option {

    return func(s *Server) { s.Tls = val } } func timeout(ts int) option { return func(s *Server) { s.Timeout = ts } } func NewServer(opts …option) (Server, error) { // defaults p := Server{false, 600, 5} for _, f := range opts { f(&p) } return p, nil } s1, e := NewServer(tls(true), timeout(9600)) s2, e := NewServer()
  34. • 29 different API integrations from Insurance companies • Interface’d

    but require different configurations - SOAP, JSON, direct SAP API, custom protocol • Dave Chaney (https://dave.cheney.net/2014/10/17/functional-options- for-friendly-apis) • Rob Pike (https://commandcenter.blogspot.com/2014/01/self- referential-functions-and-design.html) • Why not just support default parameters?
  35. • 29 different API integrations from Insurance companies • Interface’d

    but require different configurations - SOAP, JSON, direct SAP API, custom protocol • Dave Chaney (https://dave.cheney.net/2014/10/17/functional-options- for-friendly-apis) • Rob Pike (https://commandcenter.blogspot.com/2014/01/self- referential-functions-and-design.html) • Why not just support default parameters? #chavedeney
  36. Possible? type IronMan struct { Fly bool SuperSpeed bool Immortal

    bool } type Powers interface { Identity() } type SuperHero struct { Powers } ironman := `{ "Powers": { "Fly": true, "SuperSpeed": false, "Immortal": false } }` var sh SuperHero json.Unmarshal([]byte(ironman), &sh) sh.Identity()
  37. Possible? type IronMan struct { Fly bool SuperSpeed bool Immortal

    bool } type Powers interface { Identity() } type SuperHero struct { Powers } ironman := `{ "Powers": { "Fly": true, "SuperSpeed": false, "Immortal": false } }` var sh SuperHero json.Unmarshal([]byte(ironman), &sh) sh.Identity() json: cannot unmarshal object into Go struct field SuperHero.Powers of type main.Powers
  38. func (sh *SuperHero) UnmarshalJSON(b []byte) error { var s struct

    { Powers map[string]bool } s.Powers = make(map[string]bool) _ = json.Unmarshal(b, &s) if s.Powers["Fly"] && s.Powers["SuperSpeed"] { sh.Powers = IronMan{} } else if s.Powers["Immortal"] && s.Powers["SuperStrength"] { sh.Powers = Thanos{} } else { sh.Powers = WTFHero{} } return nil } UnmarshalJSON
  39. func (sh *SuperHero) UnmarshalJSON(b []byte) error { var s struct

    { Powers map[string]bool } s.Powers = make(map[string]bool) _ = json.Unmarshal(b, &s) if s.Powers["Fly"] && s.Powers["SuperSpeed"] { sh.Powers = IronMan{} } else if s.Powers["Immortal"] && s.Powers["SuperStrength"] { sh.Powers = Thanos{} } else { sh.Powers = WTFHero{} } return nil } UnmarshalJSON
  40. Zero Trust Access •Making the VPN obsolete. •Continuous authorization for

    Hybrid and Multi Cloud •Integration with different MDMs •Integration with different IDPs Federated OpenID Connect provider
  41. Dex Storage Connectors // ConnectorConfig is a configuration that can

    open a connector. type ConnectorConfig interface { Open(id string, logger logrus.FieldLogger) (connector.Connector, error) } // ConnectorsConfig variable provides an easy way to return a config struct // depending on the connector type. var ConnectorsConfig = map[string]func() ConnectorConfig{ "github": func() ConnectorConfig { return new(github.Config) }, "oidc": func() ConnectorConfig { return new(oidc.Config) }, "saml": func() ConnectorConfig { return new(saml.Config) }, "microsoft": func() ConnectorConfig { return new(microsoft.Config) }, }
  42. To exit or not to exit func main() { var

    result int for i := 0; i < 8; i++ { go func() { for { result++ } }() } // spawn the go-routines time.Sleep(time.Second) fmt.Println("exiting...") } main() is non-blocking No WaitGroups
  43. To exit or not to exit func main() { var

    result int for i := 0; i < 8; i++ { go func() { for { result++ } }() } // spawn the go-routines time.Sleep(time.Second) fmt.Println("exiting...") } main() is non-blocking No WaitGroups
  44. Zephyr • Next Generation Vinyl Record Player • Raspberry Pi

    & Arduino • 2 motors and 4 limit sensors monitored using go-routines. • Continuous Computing for platter motor next position to maintain 33.5 or 45 rpm
  45. 4 #RetireBy40 Financial freedom No daily office routine Work because

    you want to, not because you need to! Do things you love to do!