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

Useful daily business packages

Tommy Mühle
September 03, 2020

Useful daily business packages

Slides of my talk at the Gophers Dresden Meetup about, in my opinion, useful packages to solve daily business challenges.

Tommy Mühle

September 03, 2020
Tweet

More Decks by Tommy Mühle

Other Decks in Programming

Transcript

  1. Tommy Mühle | tommy-muehle.io Tommy Mühle Software Engineer and Author

    1
  2. Tommy Mühle | tommy-muehle.io Useful daily business packages 2

  3. Tommy Mühle | tommy-muehle.io Why did I selected these packages?

    3 Speaker notes:
 * To give you some context
  4. Tommy Mühle | tommy-muehle.io 4 Speaker notes:
 * Imagine you’ve

    an eCommerce shop with customers
  5. Tommy Mühle | tommy-muehle.io 5 Speaker notes:
 * or an

    service with users / communities
  6. Tommy Mühle | tommy-muehle.io 6 Speaker notes:
 * In most

    cases we’ve to deal with user generated data
  7. Tommy Mühle | tommy-muehle.io Disclaimer 7 Speaker notes:
 * I

    didn’t used every library personally * But starred it on Github for the case I came in the situation
  8. Tommy Mühle | tommy-muehle.io Date and time 8

  9. Tommy Mühle | tommy-muehle.io jinzhu/now 9

  10. Tommy Mühle | tommy-muehle.io 10 package main import ( "time"

    "github.com/jinzhu/now" ) func main() { time.Now() // 2020-08-31 22:04:25.54499 +0200 CEST m=+0.000405346 now.BeginningOfYear() // 2020-01-01 00:00:00 +0100 CET now.EndOfWeek() // 2020-09-05 23:59:59.999999999 +0200 CEST } Speaker notes:
 * Many pre-defined functions like EndOfWeek, StartOfWeek * Based on current time
  11. Tommy Mühle | tommy-muehle.io 11 package main import ( "time"

    "github.com/jinzhu/now" ) func main() { location, _ := time.LoadLocation("Europe/Berlin") c := &now.Config{ WeekStartDay: time.Monday, TimeLocation: location, TimeFormats: []string{"2006-01-02 15:04:05"}, } t := time.Date(2013, 11, 18, 17, 51, 49, 123456789, location) _ = c.With(t).BeginningOfWeek() // 2013-11-18 00:00:00 +0100 CET } Speaker notes:
 * But it’s also possible with configured time
  12. Tommy Mühle | tommy-muehle.io rickar/cal 12

  13. Tommy Mühle | tommy-muehle.io 13 package main import ( "time"

    “github.com/rickar/cal/v2" "github.com/rickar/cal/v2/us" ) func main() { c := cal.NewBusinessCalendar() c.AddHoliday( us.NewYear, us.ChristmasDay, ) c.SetWorkday(time.Saturday, true) c.SetWorkHours(8*time.Hour, 18*time.Hour+30*time.Minute) } Speaker notes:
 * Create your own custom business calendar
  14. Tommy Mühle | tommy-muehle.io 14 package main import ( "time"

    "github.com/rickar/cal/v2" ) func main() { // ... t := time.Now() if c.IsWorkday(t) { // ... } if c.WorkdaysRemain(t) == 0 { // ... } } Speaker notes:
 * Interact with them * For example check if its the last workday so that you send out receipts, emails etc * Or is it holiday
  15. Tommy Mühle | tommy-muehle.io Data processing 15

  16. Tommy Mühle | tommy-muehle.io go-playground/validator 16 Speaker notes:
 * What

    is the first thing what you do with customer data? * Validate
  17. Tommy Mühle | tommy-muehle.io 17 package main type User struct

    { FirstName string `validate:"required"` LastName string `validate:"required"` Age uint8 `validate:"gte=0,lte=130"` Email string `validate:"required,email"` IsAwesome string `validate:"is-awesome"` // custom } // ... func isAwesome(value string) bool { return value == "is-awesome" } Speaker notes:
 * Use pre-defined validators like required, email etc
  18. Tommy Mühle | tommy-muehle.io 18 package main import ( "github.com/go-playground/validator"

    ) var validate *validator.Validate func main() { validate = validator.New() validate.RegisterValidation("is-awesome", isAwesome) user := &User{ FirstName: "John", Email: "invalid-email", } err := validate.Struct(user) if err != nil { // ... } } Speaker notes:
 * Or add easily own ones
  19. Tommy Mühle | tommy-muehle.io nyaruka/phonenumbers 19

  20. Tommy Mühle | tommy-muehle.io 20 package main import ( "github.com/nyaruka/phonenumbers"

    ) func main() { num, err := phonenumbers.Parse("03518757545", "DE") if err != nil { // ... } // save only parsable phone numbers phonenumbers.Format(num, phonenumbers.NATIONAL) // 0351 8757545 phonenumbers.Format(num, phonenumbers.INTERNATIONAL) // +49 351 8757545 } Speaker notes:
 * It’s a Go port of the Google Java library
  21. Tommy Mühle | tommy-muehle.io montanaflynn/stats 21

  22. Tommy Mühle | tommy-muehle.io 22 package main import ( "github.com/montanaflynn/stats"

    ) func main() { // Age of our users ages := stats.LoadRawData([]int{30, 35, 18, 25, 23, 27}) median, err := stats.Median(ages) if err != nil { // ... } _ = median // 26 } Speaker notes:
 * Sometimes you’ve to do statistic calculations * Almost all possible functions available
  23. Tommy Mühle | tommy-muehle.io 23 package main import ( "github.com/montanaflynn/stats"

    ) func main() { // Size of our users (in mm) sizes := stats.LoadRawData([]int{150, 170, 180, 201, 190, 165, 178}) mean, err := stats.Mean(sizes) if err != nil { // ... } deviation, err := stats.StandardDeviation(sizes) if err != nil { // ... } _ = mean // 176.28571428571428 _ = deviation // 15.46160484845593 }
  24. Tommy Mühle | tommy-muehle.io mingrammer/commonregex 24

  25. Tommy Mühle | tommy-muehle.io 25 package main import ( cregex

    "github.com/mingrammer/commonregex" ) func main() { text := `John, please get that article on www.linkedin.com or www.xing.com.` _ = cregex.Links(text) // [www.linkedin.com www.xing.com] _ = cregex.Phones(`You can reach me at (519)-236-2723`) // [(519)-236-2723] } Speaker notes:
 * Sometimes you want to extract some parts out of a text * To filter spam or not allowed content
  26. Tommy Mühle | tommy-muehle.io File and image handling 26

  27. Tommy Mühle | tommy-muehle.io disintegration/imaging 27

  28. Tommy Mühle | tommy-muehle.io 28 package main import ( "github.com/disintegration/imaging"

    ) func main() { image, err := imaging.Open("source.jpg") if err != nil { // ... } // Resize the image newImage := imaging.Resize(image, 256, 256, imaging.Lanczos) // Add a blur effect _ = imaging.Blur(newImage, 0.5) } Speaker notes:
 * Basic image processing * We can use it for example to create profile pictures
  29. Tommy Mühle | tommy-muehle.io graymeta/stow 29 Speaker notes:
 * File

    abstraction layer
 * For example to store your user or product images
  30. Tommy Mühle | tommy-muehle.io 30 package main import ( "github.com/graymeta/stow"

    "github.com/graymeta/stow/s3" ) func main() { config := stow.ConfigMap{ s3.ConfigAccessKeyID: "246810", s3.ConfigSecretKey: "abc123", s3.ConfigRegion: "eu-west-1", } location, err := stow.Dial("s3", config) if err != nil { // ... } defer location.Close() // ... } Speaker notes:
 * Concept is Location (for example S3) -> Container (group of items) -> Item (single file) * First of all you need a location
  31. Tommy Mühle | tommy-muehle.io 31 package main func main() {

    // ... c, err := location.CreateContainer("profile_pictures") if err != nil { // ... } // "i" created via os.Open and "s" via image.Stat().Size() _, err = c.Put("avatar.jpg", i, s, map[string]interface{}{}) if err != nil { // ... } } Speaker notes:
 * Create a container and add files to it * Later you can walk over containers, collect items and process them
  32. Tommy Mühle | tommy-muehle.io corona10/goimagehash 32

  33. Tommy Mühle | tommy-muehle.io 33 package main import ( "image/jpeg"

    "os" "github.com/corona10/goimagehash" ) func main() { file1, _ := os.Open("Poolbild.jpg") file2, _ := os.Open("Poolbild.jpg") defer file1.Close() defer file2.Close() img1, _ := jpeg.Decode(file1) img2, _ := jpeg.Decode(file2) hash1, _ := goimagehash.AverageHash(img1) hash2, _ := goimagehash.AverageHash(img2) distance, _ := hash1.Distance(hash2) // 0 } Speaker notes:
 * Use it if you want to know which users uses the same profile picture * You can calculate the hash for every image and later find duplicates easily
 * There are more hashing algorithms available
  34. Tommy Mühle | tommy-muehle.io Security 34

  35. Tommy Mühle | tommy-muehle.io sethvargo/go-password 35

  36. Tommy Mühle | tommy-muehle.io 36 package main import ( "github.com/sethvargo/go-password/password"

    ) func main() { // Generate a password that is 32 characters long with 10 digits, 2 symbols, allowing upper and 
 lower case letters, disallowing repeat characters pass, err := password.Generate(32, 10, 2, false, false) if err != nil { // ... } _ = pass // 73g6QcNDj2BqH:FZiMeW`09ItV51EO84 } Speaker notes:
 * Based on requirements as described by AgileBits 1Password
  37. Tommy Mühle | tommy-muehle.io Testing 37

  38. Tommy Mühle | tommy-muehle.io ory/dockertest 38

  39. Tommy Mühle | tommy-muehle.io 39 package main import ( "github.com/ory/dockertest/v3"

    ) func main() { pool, _ := dockertest.NewPool("") // pulls an image, creates a container based on it and 
 runs it resource, _ := pool.Run("mysql", "5.7", []string{"MYSQL_ROOT_PASSWORD=secret"}) } Speaker notes:
 * If you want not only to mock dependencies * Easily interact with Docker in integration tests
  40. Tommy Mühle | tommy-muehle.io 40 package main import ( "database/sql"

    "log" ) func main() { // ... var err error var db *sql.DB if err = pool.Retry(func() error { db, _ = sql.Open("mysql", "...") return db.Ping() }); err != nil { ... } // Your code _ = pool.Purge(resource) } Speaker notes:
 * The retry is needed because you need to wait until the container is ready
 * Purge the container at the end
  41. Tommy Mühle | tommy-muehle.io Summary 41 Speaker notes:
 * I

    hope you found at least one interesting package that you can use for your daily work
  42. Questions?

  43. Thank you! @tommy_muehle