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

Essentials of Golang

Essentials of Golang

Presentation for Go All-stars 2

Shintaro Kaneko

October 02, 2016
Tweet

More Decks by Shintaro Kaneko

Other Decks in Programming

Transcript

  1. Go Proverbs • Go Proverbs - Rob Pike - Gopherfest

    - November 18, 2015 • https://www.youtube.com/watch?v=PAAkCSZUG1c • go-proverbs.github.io • https://go-proverbs.github.io
  2. Go Proverbs • Don't communicate by sharing memory, share memory

    by communicating. • The bigger the interface, the weaker the abstraction. • Gofmt's style is no one's favorite, yet gofmt is everyone's favorite. • A little copying is better than a little dependency. • Clear is better than clever. • Reflection is never clear. • etc..
  3. Constants • Constants are interpreted at compile-time • Definable; •

    Numbers, characters (runes), strings or booleans • Evaluatable; • ⭕ Thousand = 10 * 3, KB = 1 << 3 • Arithmetic and Bit operations • ❌ math.Pow(10, 3) • math.Pow needs to happen at run time.
  4. Constants const ( likeFromMe = 1 << 0 likeFromPartner =

    1 << 1 blockFromMe = 1 << 2 blockFromPartner = 1 << 3 mutualLike = likeFromMe | likeFromPartner ) func main() { // do something if status^mutualLike == 0 { fmt.Printf("Matching status: %b\n", status) } }
  5. Constants with iota • The ninth letter of the Greek

    alphabet (Ι, ι) • Pronunciations; • ೔ຊਓɿΠΦλ • ֎ਓɿōŘśŏŦ (ʌɪˈəʊtə) • Enumeration constants • Expressions can be implicitly repeated
  6. Constants with iota const ( likeFromMe = 1 << iota

    // 1 (1 << 0) likeFromPartner // 10 (1 << 1) blockFromMe // 100 (1 << 2) blockFromPartner // 1000 (1 << 3) index = iota // 4 mask = 1<<index - 1 // 1111 (1 << 4 - 1) mutualLike = likeFromMe | likeFromPartner )
  7. Constants with type type relationshipStatus uint32 const ( likeFromMe relationshipStatus

    = 1 << iota likeFromPartner blockFromMe blockFromPartner mutualLike = likeFromMe | likeFromPartner ) func (st relationshipStatus) isMatching() bool { return st^mutualLike == 0 } // if status.isMatching() { .. }
  8. Constants - others // _ = iota instead of iota

    + 1 const ( _ = iota // ignore first value by assigning to blank identifier KB uint64 = 1 << (10 * iota) MB GB ) // If you use iota + 1 for above example, don't forget parenthesis of "iota + 1". // ⭕ 1 << (10 * (iota + 1)) // ❌ 1 << (10 * iota + 1) // Available for constants to assign other package constants. const Day = 24 * time.Hour // time.Hour is constant. // ❌ var Day = 24 * time.Hour
  9. • Table-driven tests • https://github.com/golang/go/wiki/TableDrivenTests • https://golang.org/src/regexp/all_test.go • Run tests

    by parallel rather than sequential • To save your time • To detect race condition Testing Techniques
  10. Table-driven tests func TestToUpper(t *testing.T) { // Table-driven tests candidates

    := []struct { src, expected string }{ {"foo", "FOO"}, {"bar", "BAR"}, } for _, c := range candidates { actual := strings.ToUpper(c.src) if c.expected != actual { // should be good error messages. t.Fatalf("Expected %v, but got %v\n", c.expected, actual) } } }
  11. Parallelize tests func TestSimple(t *testing.T) { // Table-driven tests candidates

    := []struct { dur time.Duration }{ {time.Second}, {2 * time.Second}, {3 * time.Second}, {4 * time.Second}, } for _, c := range candidates { c := c // capture t.Run(fmt.Sprintf("%v", c.dur), func(t *testing.T) { t.Parallel() time.Sleep(c.dur) }) } }
  12. Parallelize tests (race condition) var cache = map[string]int{} func TestSimple(t

    *testing.T) { candidates := []struct { key string, value int }{ .. } for _, c := range candidates { c := c // capture t.Run(c.key, func(t *testing.T) { t.Parallel() // read and/or write something with cache variable. }) } }
  13. regexp.Regexp • Implementation of regexp.Regexp • Safe for use by

    concurrent goroutines • Initialization cost performance is not good • Avoid initializing as locals in functions
  14. regexp.Regexp - Benchmark code func BenchmarkRegexpMustCompile1(b *testing.B) { b.ResetTimer() for

    i := 0; i < b.N; i++ { re := regexp.MustCompile("[a-z]{3}") // ❌ _ = re.FindAllString(`Lorem ipsum dolor sit amet, consectetur..`) } } func BenchmarkRegexpMustCompile2(b *testing.B) { re := regexp.MustCompile("[a-z]{3}") // ⭕ b.ResetTimer() for i := 0; i < b.N; i++ { _ = re.FindAllString(`Lorem ipsum dolor sit amet, consectetur..`) } }
  15. regexp.Regexp - Benchmark result • BenchmarkRegexpMustCompile1-16 • 5000 385760 ns/op

    100850 B/op 830 allocs/op • BenchmarkRegexpMustCompile2-16 • 5000 367423 ns/op 59961 B/op 805 allocs/op Using Huge Data
  16. regexp.Regexp.Copy • Implementation of regexp.Regexp • Safe for use by

    concurrent goroutines • Using a sync.Mutex to protect a cache • Causes degraded performance using the same Regexp • Copy method is available for go1.6 or later
  17. regexp.Regexp.Copy - Benchmark code func BenchmarkParallelRegexpMustCompileCopy(b *testing.B) { re :=

    regexp.MustCompile("[a-z]{3}") b.ResetTimer() b.RunParallel(func(pb *testing.PB) { // Copy Regexp // https://golang.org/src/regexp/all_test.go?s=20028:20077#L718 re := re.Copy() // ❤ for pb.Next() { _ = re.FindAllString(`Lorem ipsum dolor sit amet, consectetur..`) } } }
  18. regexp.Regexp.Copy - Benchmark result • BenchmarkParallelRegexpMustCompileNoCopy-16 • 5000 375899 ns/op

    99689 B/op 817 allocs/op • BenchmarkParallelRegexpMustCompileCopy-16 • 30000 56602 ns/op 59976 B/op 805 allocs/op Using Huge Data and Parallal Benchmarking
  19. Summaries • Keep Go Proverbs of Rob Pike in your

    mind to write go code. • https://go-proverbs.github.io • Understand how to handle Constants. • Parallelism Testing and Benchmarking. • Not to put regexp on your code as possible. • Use strings package instead of it. • (And) Read Release Notes • https://golang.org/doc/go1.7