SlideShare a Scribd company logo
1 of 41
Download to read offline
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 1/41
ACCELERATING API DEVELOPMENT:
A Pit Stop with Gin-Gonic 🥃in Golang
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 2/41
PANORAMICA DEL TALK
Introduzione
Panoramica di GoLang
Introduzione a Gin
Confronto tra Gin/Echo/Fiber
Architettura del Progetto gof1
Creazione di API RESTful con Gin
Tests
Q&A
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 3/41
CHI SONO
Backend Developer - Cybersecurity Enthusiast
Sviluppo principalmente in Golang. Nel tempo libero mi interesso di Crypto e
Cybersecurity.
| |
GitHub LinkedIn X
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 4/41
STORIA E SVILUPPO DI GOLANG
GoLang, spesso chiamato Go, è stato sviluppato da Google nel 2007. È stato progettato per
migliorare la produttività nella programmazione grazie alla sua semplicità e alla sua
capacità di gestire sistemi di grandi dimensioni.
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 5/41
VANTAGGI DI GOLANG
Go è noto per la sua efficienza e performance, simile al C, ma con una sintassi più pulita.
Supporta la concorrenza, fondamentale nell'era del cloud computing.
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 6/41
CARATTERISTICHE PRINCIPALI DI GOLANG
Le goroutines sono una delle caratteristiche chiave di Go, permettendo la concorrenza
leggera e efficiente. L'uso delle interfacce e una robusta gestione degli errori rendono Go
un linguaggio potente e flessibile.
// Esempio di Goroutine
go func() {
fmt.Println("Esecuzione concorrente")
}()
26/01/24, 10:35 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 7/41
INTRODUZIONE A GIN GONIC
Gin è un framework web HTTP in Go che offre prestazioni ottimali grazie al suo design
minimalista. È uno dei framework più popolari e veloci per Go.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 8/41
CARATTERISTICHE DI GIN
Gin fornisce un routing potente, gestione degli errori, middleware e la capacità di creare
API RESTful con facilità. La sua struttura consente di scrivere applicazioni meno verbali e
più efficienti.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 9/41
ESEMPIO DI ENDPOINT CON GIN
Ecco un semplice esempio di un endpoint API scritto con Gin:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // Ascolta sulla porta 8080 per default
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 10/41
CONFRONTO TRA FRAMEWORK WEB IN GO
🔍Esaminiamo Gin, Echo e Fiber per capire le loro differenze e i punti di forza.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 11/41
GIN GONIC ✅
Gin è noto per la sua velocità e semplicità. Offre un routing performante, middleware facile
da usare e ottima gestione degli errori.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 12/41
ECHO
Echo è un framework altamente personalizzabile con funzionalità come il binding
automatico e il rendering di template. Tuttavia, può essere più verboso di Gin.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 13/41
FIBER
Fiber si ispira a Express.js e punta sulla facilità d'uso. Nonostante sia user-friendly, in
alcuni casi non raggiunge le prestazioni di Gin.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 14/41
PERCHÉ GIN?
🏆Gin equilibra velocità, facilità d'uso e funzionalità, rendendolo ideale per una vasta
gamma di applicazioni web in Go.
Ecco alcuni dati di benchmark che mostrano le prestazioni di Gin rispetto a Echo e Fiber:
Framework Richieste al secondo Latenza media
Gin 12345 req/s 0.2 ms
Echo 11789 req/s 0.25 ms
Fiber 12001 req/s 0.22 ms
⚡Questi risultati dimostrano la superiore efficienza di Gin in termini di gestione delle
richieste e bassa latenza.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 15/41
ARCHITETTURA DEL PROGETTO GOF1
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 16/41
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 17/41
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 18/41
CONTROLLER
I Controller gestiscono la logica di interazione con l'utente, ricevendo richieste e inviando
risposte.
type Controller struct {
Service F1Service
DB *gorm.DB
}
type Options struct {
Database string
}
10
11
12
13
14
15
16
17
18
19
func NewController(opts Options) Controller {
20
db, err := config.ConnectSqlite3(opts.Database)
21
if err != nil {
22
log.Fatal(err)
23
}
24
repositories := repositories.F1Repository{
25
DB: db,
26
}
27
service := services.F1Service{
28
Repository: repositories,
29
}
30
c := Controller{
31
Service: service,
32
func NewController(opts Options) Controller {
db, err := config.ConnectSqlite3(opts.Database)
if err != nil {
log.Fatal(err)
}
repositories := repositories.F1Repository{
DB: db,
}
service := services.F1Service{
Repository: repositories,
}
c := Controller{
Service: service,
DB db
10
type Controller struct {
11
Service F1Service
12
DB *gorm.DB
13
}
14
15
type Options struct {
16
Database string
17
}
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 19/41
DB: db,
33
}
34
return c
35
}
36
37
DB: db,
}
return c
}
33
34
35
36
37
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 20/41
INTERFACCE
Le interfacce in Go definiscono le firme per i nostri Service e Repository.
type F1Service interface {
AddDriver(driver models.Driver) error
GetDriver(id int) (models.Driver, error)
GetDrivers(page, limit int) ([]models.Driver, error)
GetDriversByYear(year int) ([]models.Driver, error)
GetDriverStandingsByYear(year int) ([]models.DriverStanding, error)
UpdateDriver(driver models.Driver) error
DeleteDriver(id int) error
ImportDriversFromCsv(record []string) error
...
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 21/41
MODELLI
I modelli definiscono le strutture dei dati che andremo ad utilizzare
type Driver struct {
gorm.Model
DriverID int `gorm:"column:id" gorm:"primary_key" csv:"driverId"`
DriverRef string `gorm:"column:driverRef" csv:"driverRef"`
Number string `gorm:"column:number" csv:"number"`
Code string `gorm:"column:code" csv:"code"`
Forename string `gorm:"column:forename" csv:"forename"`
Surname string `gorm:"column:surname" csv:"surname"`
DOB time.Time `gorm:"column:dob" csv:"dob"`
Nationality string `gorm:"column:nationality" csv:"nationality"`
URL string `gorm:"column:url" csv:"url"`
}
...
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 22/41
SERVICE
I Service contengono la logica e interagiscono con i Repository per l'accesso ai dati.
func (s *F1Service) GetDriver(id int) (models.Driver, error) {
return s.Repository.GetDriver(id)
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 23/41
REPOSITORY
I Repository sono responsabili dell'interazione diretta con il database, eseguendo query e
aggiornamenti.
func (r *F1Repository) GetDriver(id int) (models.Driver, error) {
var driver models.Driver
r.DB.First(&driver, id)
return driver, nil
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 24/41
SERVICE
... ma aumentiamo di poco la complessità...
func (f F1Service) GetDriverStandingsByYear(year int)
([]models.DriverStanding, error) {
if year < 1950 || year > time.Now().Year() {
return nil, fmt.Errorf("year is out of valid range")
}
standings, err := f.Repository.GetDriverStandingsByYear(year)
if err != nil {
return nil, fmt.Errorf("error retrieving driver standings: %w", err)
}
if len(standings) == 0 {
return nil, fmt.Errorf("no driver standings found for year %d", year)
}
return standings, nil
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 25/41
REPOSITORY
func (r F1Repository) GetDriverStandingsByYear(year int)
([]models.DriverStanding, error) {
var standings []models.DriverStanding
err := r.DB.
Table("results").
Select("drivers.id, drivers.forename, drivers.surname,
SUM(results.points) as points").
Joins("JOIN drivers on drivers.id = results.driverId").
Joins("JOIN races on races.id = results.raceId").
Where("races.year = ?", year).
Group("drivers.id, drivers.forename, drivers.surname").
Order("SUM(results.points) DESC").
Scan(&standings).Error
return standings, err
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 26/41
CREAZIONE DI API RESTFUL CON GIN
Illustreremo come Gin semplifica lo sviluppo di API RESTful, focalizzandoci su routing,
parametri, middleware e operazioni CRUD.
databaseFlag, _ := rootCmd.PersistentFlags().GetString("database")
10
...
11
12
13
opts := pkg.Options{
14
Database: databaseFlag,
15
}
16
17
newController := pkg.NewController(opts)
18
19
router := gin.New()
20
setupRouter(router, newController)
21
22
router.Run(":" + port)
23
...
24
opts := pkg.Options{
Database: databaseFlag,
}
newController := pkg.NewController(opts)
router := gin.New()
10
...
11
databaseFlag, _ := rootCmd.PersistentFlags().GetString("database")
12
13
14
15
16
17
18
19
20
setupRouter(router, newController)
21
22
router.Run(":" + port)
23
...
24
setupRouter(router, newController)
10
...
11
databaseFlag, _ := rootCmd.PersistentFlags().GetString("database")
12
13
opts := pkg.Options{
14
Database: databaseFlag,
15
}
16
17
newController := pkg.NewController(opts)
18
19
router := gin.New()
20
21
22
router.Run(":" + port)
23
...
24
router.Run(":" + port)
10
...
11
databaseFlag, _ := rootCmd.PersistentFlags().GetString("database")
12
13
opts := pkg.Options{
14
Database: databaseFlag,
15
}
16
17
newController := pkg.NewController(opts)
18
19
router := gin.New()
20
setupRouter(router, newController)
21
22
23
...
24
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 27/41
CONFIGURAZIONE DELLE ROUTE
Le route GET non richiedono autenticazione, rendendo le informazioni disponibili
pubblicamente.
func setupRouter(router *gin.Engine, controller pkg.Controller) {
v1 := router.Group("/v1")
{
v1.GET("/driver/:id", api.GetDriver(controller))
v1.GET("/drivers/", api.GetDrivers(controller))
v1.GET("/drivers/year/:year", api.GetDriversByYear(controller))
v1.GET("/drivers/standings/:year",
api.GetDriverStandingsByYear(controller))
}
50
51
52
53
54
55
56
57
58
59
v1Auth := router.Group("/v1")
60
{
61
v1Auth.Use(BasicAuth())
62
{
63
v1Auth.POST("/drivers", api.AddDriver(controller))
64
}
65
}
66
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 28/41
}
67
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 29/41
CONFIGURAZIONE DELLA BASIC AUTH CON GIN
Utilizzo del middleware di Gin per applicare la Basic Auth a specifiche route.
// BasicAuth middleware
// Username: admin, Password: password
func BasicAuth() gin.HandlerFunc {
return gin.BasicAuth(gin.Accounts{
"admin": "password",
})
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 30/41
CONFIGURAZIONE DELLE ROUTE
Le route POST richiedono invece autenticazione, mettiamo come middleware BasicAuth()
v1Auth := router.Group("/v1")
{
v1Auth.Use(BasicAuth())
{
v1Auth.POST("/drivers", api.AddDriver(controller))
}
}
1
func setupRouter(router *gin.Engine, controller pkg.Controller) {
2
v1 := router.Group("/v1")
3
{
4
v1.GET("/driver/:id", api.GetDriver(controller))
5
v1.GET("/drivers/", api.GetDrivers(controller))
6
v1.GET("/drivers/year/:year", api.GetDriversByYear(controller))
7
}
8
9
10
11
12
13
14
15
16
}
17
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 31/41
ESEMPIO
Prendiamo in esempio GetDriverStandingsByYear() visto prima e proviamo ora ad
assemlare i pezzi
func GetDriverStandingsByYear(controller pkg.Controller) gin.HandlerFunc
{
1
2
return func(c *gin.Context) {
3
driverIDStr := c.Param("year")
4
driverID, err := strconv.Atoi(driverIDStr)
5
if err != nil {
6
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid year param"})
7
return
8
}
9
driverStanding, err :=
controller.Service.GetDriverStandingsByYear(driverID)
10
if err != nil {
11
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
12
return
13
}
14
c.JSON(http.StatusOK, driverStanding)
15
}
16
driverIDStr := c.Param("year")
driverID, err := strconv.Atoi(driverIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid year param"})
return
}
1
func GetDriverStandingsByYear(controller pkg.Controller) gin.HandlerFunc
{
2
return func(c *gin.Context) {
3
4
5
6
7
8
9
driverStanding, err :=
controller.Service.GetDriverStandingsByYear(driverID)
10
if err != nil {
11
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
12
return
13
}
14
c.JSON(http.StatusOK, driverStanding)
15
}
16
}
17
driverStanding, err :=
controller.Service.GetDriverStandingsByYear(driverID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, driverStanding)
1
func GetDriverStandingsByYear(controller pkg.Controller) gin.HandlerFunc
{
2
return func(c *gin.Context) {
3
driverIDStr := c.Param("year")
4
driverID, err := strconv.Atoi(driverIDStr)
5
if err != nil {
6
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid year param"})
7
return
8
}
9
10
11
12
13
14
15
}
16
}
17
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 32/41
}
17
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 33/41
CURL
Proviamo ora a fare la richiesta con cUrl
curl localhost:8080/v1/drivers/standings/2023 | jq
[
{
"forename": "Max",
"surname": "Verstappen",
"points": 292
},
{
"forename": "Sergio",
"surname": "Pérez",
"points": 174
},
{
"forename": "Lewis",
"surname": "Hamilton",
"points": 144
},
...
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 34/41
]
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 35/41
TESTS
INTRODUZIONE AI TEST IN GO
I test in Go sono scritti utilizzando il pacchetto `testify`.
La convenzione prevede che i file di test abbiano il suffisso `_test.go`.
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 36/41
STRUTTURA DEL PROGETTO PER I TEST
È comune avere una struttura del progetto separata per i test. Ad esempio:
project/
├── main/
│ ├── main.go
│ └── ...
├── pkg/
│ ├── main.go
│ ├── controller.go
│ ├── service.go
│ └── ...
└── test/
├── main_test.go
├── controller_test.go
├── service_test.go
└── ...
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 37/41
ESECUZIONE DEI TEST
Eseguire i test è semplice utilizzando il comando `go test` dalla radice del progetto:
E modifica i test utilizzando assert:
$ go get github.com/stretchr/testify
import "github.com/stretchr/testify/assert"
func TestExample(t *testing.T) {
assert.Equal(t, 123, 123, "they should be equal")
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 38/41
ESEMPIO DI TEST PER IL CONTROLLER
Creiamo un file di test `controller_test.go` per il package `pkg`.
func TestGetDriver(t *testing.T) {
// Setup
controller := NewController(Options{
Database: "test.db",
})
t.Run("GetDriver - Valid ID", func(t *testing.T) {
req, _ := http.NewRequest("GET", "/v1/driver/1", nil)
resp := httptest.NewRecorder()
router := gin.New()
setupRouter(router, controller)
router.ServeHTTP(resp, req)
assert.Equal(t, http.StatusOK, resp.Code)
})
}
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 39/41
Q&A
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 40/41
GRAZIE
Se avete ulteriori domande o feedback, non esitate a contattarmi.
SEGUIMI SUI SOCIAL
@xm1k3
@mihai-gabriel-canea
26/01/24, 10:36 Gof1 Talk
https://xm1k3.github.io/gof1-talk-ita/ 41/41
@xm1k3_
Speaker notes

More Related Content

Similar to Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf

Sviluppare applicazioni geolocalizzate per iPhone
Sviluppare applicazioni geolocalizzate per iPhoneSviluppare applicazioni geolocalizzate per iPhone
Sviluppare applicazioni geolocalizzate per iPhoneEduard Roccatello
 
Linux Embedded per l'automazione
Linux Embedded per l'automazioneLinux Embedded per l'automazione
Linux Embedded per l'automazioneDaniele Costarella
 
OCA: da Oggi Contribuisco Anch'io!
OCA: da Oggi Contribuisco Anch'io!OCA: da Oggi Contribuisco Anch'io!
OCA: da Oggi Contribuisco Anch'io!Alex Comba
 
Un backend per tutte le stagioni con Spring
Un backend per tutte le stagioni con SpringUn backend per tutte le stagioni con Spring
Un backend per tutte le stagioni con SpringMarcello Teodori
 
Introduzione a libavfilter
Introduzione a libavfilterIntroduzione a libavfilter
Introduzione a libavfilterStefano Sabatini
 
Ionic Cordova vs React Native
Ionic Cordova vs React NativeIonic Cordova vs React Native
Ionic Cordova vs React NativeAntonio Gallo
 
Git – lo stupido gestore di contenuti
Git – lo stupido gestore di contenutiGit – lo stupido gestore di contenuti
Git – lo stupido gestore di contenutiGiulio Caccin
 
Javascript e Firebug per lo sviluppo Web 3.0
Javascript e Firebug per lo sviluppo Web 3.0Javascript e Firebug per lo sviluppo Web 3.0
Javascript e Firebug per lo sviluppo Web 3.0Guido Brugnara
 
Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5Marcello Teodori
 
Lo sbarco di Google nel pianeta Mobile Internet: primo impatto ed esempi pra...
Lo sbarco di Google nel pianeta Mobile Internet:  primo impatto ed esempi pra...Lo sbarco di Google nel pianeta Mobile Internet:  primo impatto ed esempi pra...
Lo sbarco di Google nel pianeta Mobile Internet: primo impatto ed esempi pra...Riccardo Solimena
 

Similar to Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf (20)

Sviluppare applicazioni geolocalizzate per iPhone
Sviluppare applicazioni geolocalizzate per iPhoneSviluppare applicazioni geolocalizzate per iPhone
Sviluppare applicazioni geolocalizzate per iPhone
 
Linux Embedded per l'automazione
Linux Embedded per l'automazioneLinux Embedded per l'automazione
Linux Embedded per l'automazione
 
Logging
LoggingLogging
Logging
 
TYPO3 CMS 7.3 - le novita
TYPO3 CMS 7.3 - le novitaTYPO3 CMS 7.3 - le novita
TYPO3 CMS 7.3 - le novita
 
OCA: da Oggi Contribuisco Anch'io!
OCA: da Oggi Contribuisco Anch'io!OCA: da Oggi Contribuisco Anch'io!
OCA: da Oggi Contribuisco Anch'io!
 
05 OCA, da Oggi Contribuisco Anch'io!
05 OCA, da Oggi Contribuisco Anch'io!05 OCA, da Oggi Contribuisco Anch'io!
05 OCA, da Oggi Contribuisco Anch'io!
 
Un backend per tutte le stagioni con Spring
Un backend per tutte le stagioni con SpringUn backend per tutte le stagioni con Spring
Un backend per tutte le stagioni con Spring
 
Introduzione a libavfilter
Introduzione a libavfilterIntroduzione a libavfilter
Introduzione a libavfilter
 
App Engine + Python
App Engine + PythonApp Engine + Python
App Engine + Python
 
XPages Tips & Tricks, #dd13
XPages Tips & Tricks, #dd13XPages Tips & Tricks, #dd13
XPages Tips & Tricks, #dd13
 
Ionic Cordova vs React Native
Ionic Cordova vs React NativeIonic Cordova vs React Native
Ionic Cordova vs React Native
 
Git – lo stupido gestore di contenuti
Git – lo stupido gestore di contenutiGit – lo stupido gestore di contenuti
Git – lo stupido gestore di contenuti
 
Wpo extended
Wpo extendedWpo extended
Wpo extended
 
Spring e Flex
Spring e FlexSpring e Flex
Spring e Flex
 
Javascript e Firebug per lo sviluppo Web 3.0
Javascript e Firebug per lo sviluppo Web 3.0Javascript e Firebug per lo sviluppo Web 3.0
Javascript e Firebug per lo sviluppo Web 3.0
 
Rx - ReactiveX
Rx - ReactiveXRx - ReactiveX
Rx - ReactiveX
 
introduzione a symfony 2
introduzione a symfony 2 introduzione a symfony 2
introduzione a symfony 2
 
TYPO3 v10.0 - Le novità
TYPO3 v10.0 - Le novitàTYPO3 v10.0 - Le novità
TYPO3 v10.0 - Le novità
 
Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5Streaming in Java e Flex con Red5
Streaming in Java e Flex con Red5
 
Lo sbarco di Google nel pianeta Mobile Internet: primo impatto ed esempi pra...
Lo sbarco di Google nel pianeta Mobile Internet:  primo impatto ed esempi pra...Lo sbarco di Google nel pianeta Mobile Internet:  primo impatto ed esempi pra...
Lo sbarco di Google nel pianeta Mobile Internet: primo impatto ed esempi pra...
 

More from Commit University

Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfCommit University
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Commit University
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit University
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PACommit University
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Commit University
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting forCommit University
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityCommit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfCommit University
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Commit University
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsCommit University
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftCommit University
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneCommit University
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcCommit University
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeCommit University
 
Alpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkAlpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkCommit University
 

More from Commit University (20)

Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
 
Slide-10years.pdf
Slide-10years.pdfSlide-10years.pdf
Slide-10years.pdf
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
 
Vue.js slots.pdf
Vue.js slots.pdfVue.js slots.pdf
Vue.js slots.pdf
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptx
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PA
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting for
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdf
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step Functions
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and Swift
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lc
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-Code
 
SwiftUI vs UIKit
SwiftUI vs UIKitSwiftUI vs UIKit
SwiftUI vs UIKit
 
Alpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkAlpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript framework
 

Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf

  • 1. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 1/41 ACCELERATING API DEVELOPMENT: A Pit Stop with Gin-Gonic 🥃in Golang
  • 2. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 2/41 PANORAMICA DEL TALK Introduzione Panoramica di GoLang Introduzione a Gin Confronto tra Gin/Echo/Fiber Architettura del Progetto gof1 Creazione di API RESTful con Gin Tests Q&A
  • 3. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 3/41 CHI SONO Backend Developer - Cybersecurity Enthusiast Sviluppo principalmente in Golang. Nel tempo libero mi interesso di Crypto e Cybersecurity. | | GitHub LinkedIn X
  • 4. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 4/41 STORIA E SVILUPPO DI GOLANG GoLang, spesso chiamato Go, è stato sviluppato da Google nel 2007. È stato progettato per migliorare la produttività nella programmazione grazie alla sua semplicità e alla sua capacità di gestire sistemi di grandi dimensioni.
  • 5. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 5/41 VANTAGGI DI GOLANG Go è noto per la sua efficienza e performance, simile al C, ma con una sintassi più pulita. Supporta la concorrenza, fondamentale nell'era del cloud computing.
  • 6. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 6/41 CARATTERISTICHE PRINCIPALI DI GOLANG Le goroutines sono una delle caratteristiche chiave di Go, permettendo la concorrenza leggera e efficiente. L'uso delle interfacce e una robusta gestione degli errori rendono Go un linguaggio potente e flessibile. // Esempio di Goroutine go func() { fmt.Println("Esecuzione concorrente") }()
  • 7. 26/01/24, 10:35 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 7/41 INTRODUZIONE A GIN GONIC Gin è un framework web HTTP in Go che offre prestazioni ottimali grazie al suo design minimalista. È uno dei framework più popolari e veloci per Go.
  • 8. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 8/41 CARATTERISTICHE DI GIN Gin fornisce un routing potente, gestione degli errori, middleware e la capacità di creare API RESTful con facilità. La sua struttura consente di scrivere applicazioni meno verbali e più efficienti.
  • 9. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 9/41 ESEMPIO DI ENDPOINT CON GIN Ecco un semplice esempio di un endpoint API scritto con Gin: package main import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() // Ascolta sulla porta 8080 per default }
  • 10. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 10/41 CONFRONTO TRA FRAMEWORK WEB IN GO 🔍Esaminiamo Gin, Echo e Fiber per capire le loro differenze e i punti di forza.
  • 11. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 11/41 GIN GONIC ✅ Gin è noto per la sua velocità e semplicità. Offre un routing performante, middleware facile da usare e ottima gestione degli errori.
  • 12. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 12/41 ECHO Echo è un framework altamente personalizzabile con funzionalità come il binding automatico e il rendering di template. Tuttavia, può essere più verboso di Gin.
  • 13. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 13/41 FIBER Fiber si ispira a Express.js e punta sulla facilità d'uso. Nonostante sia user-friendly, in alcuni casi non raggiunge le prestazioni di Gin.
  • 14. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 14/41 PERCHÉ GIN? 🏆Gin equilibra velocità, facilità d'uso e funzionalità, rendendolo ideale per una vasta gamma di applicazioni web in Go. Ecco alcuni dati di benchmark che mostrano le prestazioni di Gin rispetto a Echo e Fiber: Framework Richieste al secondo Latenza media Gin 12345 req/s 0.2 ms Echo 11789 req/s 0.25 ms Fiber 12001 req/s 0.22 ms ⚡Questi risultati dimostrano la superiore efficienza di Gin in termini di gestione delle richieste e bassa latenza.
  • 15. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 15/41 ARCHITETTURA DEL PROGETTO GOF1
  • 16. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 16/41
  • 17. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 17/41
  • 18. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 18/41 CONTROLLER I Controller gestiscono la logica di interazione con l'utente, ricevendo richieste e inviando risposte. type Controller struct { Service F1Service DB *gorm.DB } type Options struct { Database string } 10 11 12 13 14 15 16 17 18 19 func NewController(opts Options) Controller { 20 db, err := config.ConnectSqlite3(opts.Database) 21 if err != nil { 22 log.Fatal(err) 23 } 24 repositories := repositories.F1Repository{ 25 DB: db, 26 } 27 service := services.F1Service{ 28 Repository: repositories, 29 } 30 c := Controller{ 31 Service: service, 32 func NewController(opts Options) Controller { db, err := config.ConnectSqlite3(opts.Database) if err != nil { log.Fatal(err) } repositories := repositories.F1Repository{ DB: db, } service := services.F1Service{ Repository: repositories, } c := Controller{ Service: service, DB db 10 type Controller struct { 11 Service F1Service 12 DB *gorm.DB 13 } 14 15 type Options struct { 16 Database string 17 } 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
  • 19. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 19/41 DB: db, 33 } 34 return c 35 } 36 37 DB: db, } return c } 33 34 35 36 37
  • 20. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 20/41 INTERFACCE Le interfacce in Go definiscono le firme per i nostri Service e Repository. type F1Service interface { AddDriver(driver models.Driver) error GetDriver(id int) (models.Driver, error) GetDrivers(page, limit int) ([]models.Driver, error) GetDriversByYear(year int) ([]models.Driver, error) GetDriverStandingsByYear(year int) ([]models.DriverStanding, error) UpdateDriver(driver models.Driver) error DeleteDriver(id int) error ImportDriversFromCsv(record []string) error ... }
  • 21. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 21/41 MODELLI I modelli definiscono le strutture dei dati che andremo ad utilizzare type Driver struct { gorm.Model DriverID int `gorm:"column:id" gorm:"primary_key" csv:"driverId"` DriverRef string `gorm:"column:driverRef" csv:"driverRef"` Number string `gorm:"column:number" csv:"number"` Code string `gorm:"column:code" csv:"code"` Forename string `gorm:"column:forename" csv:"forename"` Surname string `gorm:"column:surname" csv:"surname"` DOB time.Time `gorm:"column:dob" csv:"dob"` Nationality string `gorm:"column:nationality" csv:"nationality"` URL string `gorm:"column:url" csv:"url"` } ...
  • 22. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 22/41 SERVICE I Service contengono la logica e interagiscono con i Repository per l'accesso ai dati. func (s *F1Service) GetDriver(id int) (models.Driver, error) { return s.Repository.GetDriver(id) }
  • 23. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 23/41 REPOSITORY I Repository sono responsabili dell'interazione diretta con il database, eseguendo query e aggiornamenti. func (r *F1Repository) GetDriver(id int) (models.Driver, error) { var driver models.Driver r.DB.First(&driver, id) return driver, nil }
  • 24. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 24/41 SERVICE ... ma aumentiamo di poco la complessità... func (f F1Service) GetDriverStandingsByYear(year int) ([]models.DriverStanding, error) { if year < 1950 || year > time.Now().Year() { return nil, fmt.Errorf("year is out of valid range") } standings, err := f.Repository.GetDriverStandingsByYear(year) if err != nil { return nil, fmt.Errorf("error retrieving driver standings: %w", err) } if len(standings) == 0 { return nil, fmt.Errorf("no driver standings found for year %d", year) } return standings, nil }
  • 25. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 25/41 REPOSITORY func (r F1Repository) GetDriverStandingsByYear(year int) ([]models.DriverStanding, error) { var standings []models.DriverStanding err := r.DB. Table("results"). Select("drivers.id, drivers.forename, drivers.surname, SUM(results.points) as points"). Joins("JOIN drivers on drivers.id = results.driverId"). Joins("JOIN races on races.id = results.raceId"). Where("races.year = ?", year). Group("drivers.id, drivers.forename, drivers.surname"). Order("SUM(results.points) DESC"). Scan(&standings).Error return standings, err }
  • 26. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 26/41 CREAZIONE DI API RESTFUL CON GIN Illustreremo come Gin semplifica lo sviluppo di API RESTful, focalizzandoci su routing, parametri, middleware e operazioni CRUD. databaseFlag, _ := rootCmd.PersistentFlags().GetString("database") 10 ... 11 12 13 opts := pkg.Options{ 14 Database: databaseFlag, 15 } 16 17 newController := pkg.NewController(opts) 18 19 router := gin.New() 20 setupRouter(router, newController) 21 22 router.Run(":" + port) 23 ... 24 opts := pkg.Options{ Database: databaseFlag, } newController := pkg.NewController(opts) router := gin.New() 10 ... 11 databaseFlag, _ := rootCmd.PersistentFlags().GetString("database") 12 13 14 15 16 17 18 19 20 setupRouter(router, newController) 21 22 router.Run(":" + port) 23 ... 24 setupRouter(router, newController) 10 ... 11 databaseFlag, _ := rootCmd.PersistentFlags().GetString("database") 12 13 opts := pkg.Options{ 14 Database: databaseFlag, 15 } 16 17 newController := pkg.NewController(opts) 18 19 router := gin.New() 20 21 22 router.Run(":" + port) 23 ... 24 router.Run(":" + port) 10 ... 11 databaseFlag, _ := rootCmd.PersistentFlags().GetString("database") 12 13 opts := pkg.Options{ 14 Database: databaseFlag, 15 } 16 17 newController := pkg.NewController(opts) 18 19 router := gin.New() 20 setupRouter(router, newController) 21 22 23 ... 24
  • 27. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 27/41 CONFIGURAZIONE DELLE ROUTE Le route GET non richiedono autenticazione, rendendo le informazioni disponibili pubblicamente. func setupRouter(router *gin.Engine, controller pkg.Controller) { v1 := router.Group("/v1") { v1.GET("/driver/:id", api.GetDriver(controller)) v1.GET("/drivers/", api.GetDrivers(controller)) v1.GET("/drivers/year/:year", api.GetDriversByYear(controller)) v1.GET("/drivers/standings/:year", api.GetDriverStandingsByYear(controller)) } 50 51 52 53 54 55 56 57 58 59 v1Auth := router.Group("/v1") 60 { 61 v1Auth.Use(BasicAuth()) 62 { 63 v1Auth.POST("/drivers", api.AddDriver(controller)) 64 } 65 } 66
  • 28. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 28/41 } 67
  • 29. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 29/41 CONFIGURAZIONE DELLA BASIC AUTH CON GIN Utilizzo del middleware di Gin per applicare la Basic Auth a specifiche route. // BasicAuth middleware // Username: admin, Password: password func BasicAuth() gin.HandlerFunc { return gin.BasicAuth(gin.Accounts{ "admin": "password", }) }
  • 30. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 30/41 CONFIGURAZIONE DELLE ROUTE Le route POST richiedono invece autenticazione, mettiamo come middleware BasicAuth() v1Auth := router.Group("/v1") { v1Auth.Use(BasicAuth()) { v1Auth.POST("/drivers", api.AddDriver(controller)) } } 1 func setupRouter(router *gin.Engine, controller pkg.Controller) { 2 v1 := router.Group("/v1") 3 { 4 v1.GET("/driver/:id", api.GetDriver(controller)) 5 v1.GET("/drivers/", api.GetDrivers(controller)) 6 v1.GET("/drivers/year/:year", api.GetDriversByYear(controller)) 7 } 8 9 10 11 12 13 14 15 16 } 17
  • 31. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 31/41 ESEMPIO Prendiamo in esempio GetDriverStandingsByYear() visto prima e proviamo ora ad assemlare i pezzi func GetDriverStandingsByYear(controller pkg.Controller) gin.HandlerFunc { 1 2 return func(c *gin.Context) { 3 driverIDStr := c.Param("year") 4 driverID, err := strconv.Atoi(driverIDStr) 5 if err != nil { 6 c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid year param"}) 7 return 8 } 9 driverStanding, err := controller.Service.GetDriverStandingsByYear(driverID) 10 if err != nil { 11 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) 12 return 13 } 14 c.JSON(http.StatusOK, driverStanding) 15 } 16 driverIDStr := c.Param("year") driverID, err := strconv.Atoi(driverIDStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid year param"}) return } 1 func GetDriverStandingsByYear(controller pkg.Controller) gin.HandlerFunc { 2 return func(c *gin.Context) { 3 4 5 6 7 8 9 driverStanding, err := controller.Service.GetDriverStandingsByYear(driverID) 10 if err != nil { 11 c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) 12 return 13 } 14 c.JSON(http.StatusOK, driverStanding) 15 } 16 } 17 driverStanding, err := controller.Service.GetDriverStandingsByYear(driverID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, driverStanding) 1 func GetDriverStandingsByYear(controller pkg.Controller) gin.HandlerFunc { 2 return func(c *gin.Context) { 3 driverIDStr := c.Param("year") 4 driverID, err := strconv.Atoi(driverIDStr) 5 if err != nil { 6 c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid year param"}) 7 return 8 } 9 10 11 12 13 14 15 } 16 } 17
  • 32. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 32/41 } 17
  • 33. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 33/41 CURL Proviamo ora a fare la richiesta con cUrl curl localhost:8080/v1/drivers/standings/2023 | jq [ { "forename": "Max", "surname": "Verstappen", "points": 292 }, { "forename": "Sergio", "surname": "Pérez", "points": 174 }, { "forename": "Lewis", "surname": "Hamilton", "points": 144 }, ...
  • 34. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 34/41 ]
  • 35. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 35/41 TESTS INTRODUZIONE AI TEST IN GO I test in Go sono scritti utilizzando il pacchetto `testify`. La convenzione prevede che i file di test abbiano il suffisso `_test.go`.
  • 36. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 36/41 STRUTTURA DEL PROGETTO PER I TEST È comune avere una struttura del progetto separata per i test. Ad esempio: project/ ├── main/ │ ├── main.go │ └── ... ├── pkg/ │ ├── main.go │ ├── controller.go │ ├── service.go │ └── ... └── test/ ├── main_test.go ├── controller_test.go ├── service_test.go └── ...
  • 37. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 37/41 ESECUZIONE DEI TEST Eseguire i test è semplice utilizzando il comando `go test` dalla radice del progetto: E modifica i test utilizzando assert: $ go get github.com/stretchr/testify import "github.com/stretchr/testify/assert" func TestExample(t *testing.T) { assert.Equal(t, 123, 123, "they should be equal") }
  • 38. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 38/41 ESEMPIO DI TEST PER IL CONTROLLER Creiamo un file di test `controller_test.go` per il package `pkg`. func TestGetDriver(t *testing.T) { // Setup controller := NewController(Options{ Database: "test.db", }) t.Run("GetDriver - Valid ID", func(t *testing.T) { req, _ := http.NewRequest("GET", "/v1/driver/1", nil) resp := httptest.NewRecorder() router := gin.New() setupRouter(router, controller) router.ServeHTTP(resp, req) assert.Equal(t, http.StatusOK, resp.Code) }) }
  • 39. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 39/41 Q&A
  • 40. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 40/41 GRAZIE Se avete ulteriori domande o feedback, non esitate a contattarmi. SEGUIMI SUI SOCIAL @xm1k3 @mihai-gabriel-canea
  • 41. 26/01/24, 10:36 Gof1 Talk https://xm1k3.github.io/gof1-talk-ita/ 41/41 @xm1k3_ Speaker notes