Successfully reported this slideshow.

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

Gtg12

  1. 1. Happy Programming with Go Compiler GTG 12 poga
  2. 2. Today • Tricks to write DSL in Go • code generation with GO GENERATE
  3. 3. DSL in Go s.Config( LogLevel(WARN), Backend(S3{ Key: "API_KEY", Secret: "SUPER SECRET", }), AfterComplete(func() { fmt.Println("service ready") }), ) Do(With{A: "foo", B: 123})
  4. 4. Ruby • DSL! • Slow
 

  5. 5. Ruby • DSL! • Slow • Error-prone
  6. 6. DSL in Ruby
  7. 7. DSL in Ruby validates :name, presence: true validate :name, presence: true validates :name, presense: true Which is correct?
  8. 8. DSL in Ruby validates :points, numericality: true validates :points, numericality: { only: “integer” } validates :points, numericality: { only_integer: true } Which is correct?
  9. 9. DSL in Ruby • String/symbol + Hash everywhere • lack of “Syntax Error” • everything is void* • anything is ok for ruby interpreter • Need a lot of GOOD documentation

  10. 10. DSL in Ruby • String/symbol + Hash everywhere • lack of “Syntax Error” • everything is void* • anything is ok for ruby interpreter • Need a lot of GOOD documentation • and memorization
  11. 11. Go • Fast • Small Footprint
 
 
 
 
 
 
 
 
 

  12. 12. Go • Fast • Small Footprint • Verbose • sort • if err != nil • if err != nil • if err != nil
  13. 13. Patterns • http://www.godesignpatterns.com/ • https://blog.golang.org/errors-are-values
  14. 14. Named Parameter type With struct { A string B int } func main() { Do(With{A: "foo", B: 123}) } func Do(p With) { … }
  15. 15. Named Parameter • Error when • mistype parameter name • incorrect parameter type
  16. 16. Configuration s.Config( LogLevel(WARN), Backend(S3{ Key: "API_KEY", Secret: "SUPER SECRET", }), AfterComplete(func() { fmt.Println("service ready") }), ) type Service struct { ErrorLevel int AWSKey string AWSSecret string AfterHook func() } https://gist.github.com/poga/bf0534486199c8e778cb
  17. 17. Configuration • Self-referential Function
 
 
 
 
 
 
 
 
 
 type option func(*Service) func (s *Service) Config(opts ...option) { for _, opt := range opts { opt(s) } } func LogLevel(level int) option { return func(s *Service) { s.ErrorLevel = level } } http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html
  18. 18. Struct Tag type Person struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` MiddleName string `json:"middle_name,omitempty"` }
  19. 19. Struct Tag • Anti-Pattern • String-typing • No compile time checking • 6 month old bug in KKTIX production, no one noticed • based on reflect • slow • Don’t use it as DSL
  20. 20. Vanilla Go • Sometimes it’s not enough • We need to go deeper
 
 
 
 
 
 

  21. 21. Code Generation WOW So Rails Much Magic
  22. 22. Error Handling in Go • Extremely Verbose • We already have 3 official error handling patterns • https://blog.golang.org/errors-are-values • checking error is fine. But I’m lazy to type • Messy control flow
  23. 23. Error Handler Generation • go get github.com/poga/autoerror • just a demo, don’t use it in production
  24. 24. Auto Error • Add error checking function based on the name of error variable • Hide error checking from control flow
  25. 25. //go:generate autoerror -i simple.go -t AutoError -o test.go type AutoError error var e AutoError var e2 AutoError func Test() { e = doSomething() e2 = doSomething() } func doSomething() error { return errors.New("an error") } func handleError2(e2 error) { if e2 != nil { panic(e) } } func handleError(e error) { if e != nil { panic(e) } }
  26. 26. //go:generate autoerror -i simple.go -t AutoError -o test.go type AutoError error var e AutoError var e2 AutoError func Test() { e = doSomething() e2 = doSomething() } func doSomething() error { return errors.New("an error") } func handleError2(e2 error) { if e2 != nil { panic(e) } } func handleError(e error) { if e != nil { panic(e) } }
  27. 27. //go:generate autoerror -i simple.go -t AutoError -o test.go type AutoError error var e AutoError var e2 AutoError func Test() { e = doSomething() e2 = doSomething() handleError2(e2) } func doSomething() error { return errors.New("an error") } func handleError2(e2 error) { if e2 != nil { panic(e) } } func handleError(e error) { if e != nil { panic(e) } }
  28. 28. //go:generate autoerror -i simple.go -t AutoError -o test.go type AutoError error var e AutoError var e2 AutoError func Test() { e = doSomething() e2 = doSomething() handleError2(e2) } func doSomething() error { return errors.New("an error") } func handleError2(e2 error) { if e2 != nil { panic(e) } } func handleError(e error) { if e != nil { panic(e) } }
  29. 29. //go:generate autoerror -i simple.go -t AutoError -o test.go type AutoError error var e AutoError var e2 AutoError func Test() { e = doSomething() handleError(e) e2 = doSomething() handleError2(e2) } func doSomething() error { return errors.New("an error") } func handleError2(e2 error) { if e2 != nil { panic(e) } } func handleError(e error) { if e != nil { panic(e) } }
  30. 30. What is Go Generate • shell scripting in go
 
 
 
 
 $ go generate //go:generate echo 'hello from go generate' hello from go generate
  31. 31. go generate • execute a ruby script • integrate with code gen tools • yacc, protocol buffer,… etc //go:generate ruby gen.rb //go:generate codecgen -o values.generated.go file1.go file2.go file3.go
  32. 32. go generate • go get won’t execute ‘go generate’ for you • generate before publish
  33. 33. type checking placeholder json.have( pair{Key: “FirstName”, From: “first_name”}, pair{Key: “FirstName”, From: “first_name”}, pair{Key: “MiddleName”, From: “middle_name”, OmitEmpty: true}) type Person struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` MiddleName string `json:"middle_name,omitempty"` }
  34. 34. person.have( string{Key: “FirstName”, From: “first_name”}, string{Key: “FirstName”, From: “first_name”}, string{Key: “MiddleName”, From: “middle_name”, OmitEmpty: true}) type Person struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` MiddleName string `json:"middle_name,omitempty"` } func (p Person) have(pairs pair…) { panic(“run go generate before use this file”) }
  35. 35. Recap • DSL • Named Parameter • Configuration • Code Generation • type checking placeholder
  36. 36. Thank you

×