Перейти к основному содержимому

Первая программа на Gin

Разработчику Архитектору

Первая программа на Gin

Gin — популярный HTTP-фреймворк поверх net/http. Подходит для API и микросервисов.

Обзор Gin/Echo/Fiber: Фреймворки и библиотеки Go. Также: Echo · Fiber. Тесты: Тестирование в Go. Чистый net/http: Пример микросервиса.


Инициализация модуля

mkdir gin-notes && cd gin-notes
go mod init example.com/gin-notes
go get github.com/gin-gonic/gin

REST API «Заметки»

main.go:

package main

import (
"net/http"
"strconv"
"sync"

"github.com/gin-gonic/gin"
)

type Note struct {
ID int `json:"id"`
Text string `json:"text" binding:"required,min=1,max=500"`
}

var (
notes []Note
nextID = 1
mu sync.Mutex
)

func main() {
r := gin.Default() // Logger + Recovery middleware

r.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})

api := r.Group("/api")
{
api.GET("/notes", listNotes)
api.POST("/notes", createNote)
api.DELETE("/notes/:id", deleteNote)
}

r.Run(":8080") // http://127.0.0.1:8080
}

func listNotes(c *gin.Context) {
mu.Lock()
defer mu.Unlock()
c.JSON(http.StatusOK, notes)
}

func createNote(c *gin.Context) {
var body Note
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
mu.Lock()
body.ID = nextID
nextID++
notes = append(notes, body)
mu.Unlock()
c.JSON(http.StatusCreated, body)
}

func deleteNote(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
return
}
mu.Lock()
defer mu.Unlock()
for i, n := range notes {
if n.ID == id {
notes = append(notes[:i], notes[i+1:]...)
c.Status(http.StatusNoContent)
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
}
go run .

Проверка

curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/notes
curl -X POST http://127.0.0.1:8080/api/notes \
-H "Content-Type: application/json" \
-d '{"text":"Изучить Gin"}'
curl -X DELETE http://127.0.0.1:8080/api/notes/1

Свой middleware

func requestLogger() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
// после обработчика
// log.Printf("%s %s %d", c.Request.Method, c.Request.URL.Path, c.Writer.Status())
}
}

// r.Use(requestLogger())

Graceful shutdown

import (
"context"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)

srv := &http.Server{Addr: ":8080", Handler: r}
go func() { _ = srv.ListenAndServe() }()

quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = srv.Shutdown(ctx)

Дальше

  • Подключить GORM / sqlx;
  • конфиг через Viper;
  • Docker — см. 241.md.

См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).