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

Useful daily business packages

C739f65cecbb38923d95e9b7cc0d2e63?s=47 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.

C739f65cecbb38923d95e9b7cc0d2e63?s=128

Tommy Mühle

September 03, 2020
Tweet

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