Save 37% off PRO during our Black Friday Sale! »

Building a webapp with go - a post mortem report - Martin Radile - Aleri Solutions

6e3ea86995d93d35c0fadf2694bca773?s=47 GoDays
January 23, 2020

Building a webapp with go - a post mortem report - Martin Radile - Aleri Solutions

This talk is a post mortem report about building a mobile first web application with go as the backend language and Vue.js as the frontend language. The focus is on the backend parts written in go.
The talk will begin with a brief overview of the problem that we solved.
The main part will then give an opinionated view of the libraries used for the most important backend parts:
Building a REST API: https://github.com/labstack/echo
We chose the echo framework because it had a good set of features helping us to speed up the development.

6e3ea86995d93d35c0fadf2694bca773?s=128

GoDays

January 23, 2020
Tweet

Transcript

  1. Building a Web App With Go A Post Mortem Report

    1 Berlin, 2020-01-23
  2. Whoami? • Martin Radile • History in Content Management •

    Backend Developer & DevOps • Developer Relations Go @ Aleri Solutions @m_radile 2
  3. What is This Talk About? • A post mortem report

    about developing a web app in go • Which libraries where useful (and why)? • Which libraries where not useful (and why)? • Some code snippets 3
  4. Task Task • Car accident reporting tool • Team of

    five (UX, PO, PM, Frontend & Backend Developer • Budget: ~45 Days Technical Requirements • Free Choice of Technology • SAML2 Login (Central IDP) • Sending Reports by Email (+Images) • Mobile first • Unkown Hosting Plattform 4
  5. Summary Frontend Single Page Application (Vue.js) Backend written in Go

    with • github.com/labstack/echo • github.com/jinzhu/gorm • github.com/russellhaering/gosaml2 • github.com/urfave/cli • github.com/GeertJohan/go.rice • github.com/sirupsen/logrus • github.com/nfnt/resize • github.com/stretchr/testify • github.com/golang/mock Finished • on time • in budget • at the promised level of quality End of Talk ;-) 5
  6. Focus on These Libraries • github.com/labstack/echo • github.com/jinzhu/gorm • github.com/russellhaering/gosaml2

    • github.com/sirupsen/logrus 6
  7. Echo Echo is a web framework • Features • Routing

    • Request binding to structs • Embedding & serving static files • Middlewares • and more… 7
  8. Echo - Basics func main() { e := echo.New() e.GET("/ping",

    func(c echo.Context) error { return c.String(http.StatusOK, "pong") }) log.Fatal(e.Start(":5000")) } 8
  9. Echo - Routing func main() { e := echo.New() e.POST("/projects",

    Add) e.GET("/projects/:id", Get) e.PUT("/projects/:id", Update) e.DELETE("/projects/:id", Delete) e.GET("/projects", All) log.Fatal(e.Start(":5000")) } 9
  10. Echo - Request & Response type Project struct { ID

    string `json:"id"` Name string `json:"name"` } func Add(c echo.Context) error { var p Project if err := c.Bind(&p); err != nil { return err } //do something with p return c.JSON(http.StatusOK, &p) } 10
  11. Echo • Easy to learn • Echo „wasn’t in the

    way“ • Excellent documentation • Lots of examples • Fun to use 11
  12. Gorm ORM in go • Most popular ORM in go

    • Relation modelling • Support for multiples DBs • Hook support (CRUD Events) • Simple Migrations • No SQL needed • DB handle accessible 12
  13. Gorm - Modelling type Person struct { ID uint `gorm:"primary_key"`

    Name string } type Role struct { ID uint `gorm:"primary_key"` Name string PersonID int Person Person } 13
  14. Gorm - Modelling type Person struct { ID uint `gorm:"primary_key"`

    Name string } type Role struct { ID uint `gorm:"primary_key"` Name string PersonID int Person Person } 14 func main() { db, _ := gorm.Open("postgres", conStr) defer db.Close() db.AutoMigrate(&Person{}) db.AutoMigrate(&Role{}) r := Role{ Name: "a role", Person: Person{ Name: "somebody", }, } if err := db.Create(&r).Error; err != nil { //handle error } }
  15. Gorm • Good for quick prototyping • Reduces boilerplate code

    • Documentation could be better • Support for multiple DBs did not work (e.g. time.Time) • On balance potentially more trouble than benefit 15
  16. gosaml2 SAML2 library • Only SAML2 implementation for go •

    Pure Go implementation • Request signing & encrypting 16
  17. Gosaml2 • Only code example as documentation • Request signing

    did not work • A lot of try & error 17
  18. Logrus Structured logging library • Multiple log formats • (colored)

    Text • JSON • + more plug-ins • Default fields • Drop in replacement for standard logging 18
  19. Logrus - Basics package main import log "github.com/sirupsen/logrus" func main()

    { log.Print(„hello godays") } ==================================================================================== INFO[0000] hello godays 19
  20. Logrus - Setup func main() { log.SetFormatter(&log.JSONFormatter{}) log.SetLevel(log.InfoLevel) log.Info(„hello godays")

    } ========================================================================================== {"level":"info","msg":"hello godays","time":"2020-01-22T19:03:39+01:00"} 20
  21. Logrus - Fields func main() { log.WithFields(log.Fields{ "project_id": 42, }).Info("added

    entry") } ==================================================================================== INFO[0000] added entry project_id=42 21
  22. Logrus - Default Fields func main() { logger := log.WithFields(log.Fields{

    "layer": "database", }) logger.Info(„connected successful") } ==================================================================================== INFO[0000] connection successful layer=database 22
  23. Logrus - Default Fields func main() { logger := log.WithFields(log.Fields{

    "layer": "database", }) logger.Info("connection succesful") logger.WithFields(log.Fields{ "project_id": 42, }).Info("added entry") } =================================================================================== INFO[0000] connection successful layer=database INFO[0000] connection successful layer=database project_id=42 23
  24. Logrus • Easy to learn • Good documentation • Default

    fields helped reducing repetition 24
  25. Conclusion • Echo did help a lot • Gorm was

    good start, but backfired later • Gosaml2 was ok, but would choose OAuth2 • Logrus was very useful • Go was a perfect fit 25
  26. Thanks :-) 26 @m_radile

  27. Gorm - Basics package main import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/postgres"

    ) func main() { con := "host=localhost port=5432 user=go dbname=go password=go sslmode=true“ db, err := gorm.Open("postgres", con) if err != nil { panic("could not connect to database") } defer db.Close() } 27