Golang + Gin で Cookie を扱う

構成

/app
  ├ /infrastructure
  │   └ Routing.go
  │
  ├ /interfaces
  │   └ /controllers
  │       ├ Context.go
  │       └ CookiesController.go
  │
  ├ /presenters
  │   └ /cookies
  │       └ index.tmpl
  │
  └ /usecase
      └ CookieInteractor.go
main.go

サンプルコード

フォームを用意してクッキーを保存させるサンプル。

main.go

package main

import (
	"github.com/psychedelicnekopunch/gin-sample/app/infrastructure"
)

func main() {
	r := infrastructure.NewRouting()
	r.Run()
}

/app/infrastructure/Routing.go


package infrastructure

import (
	"github.com/gin-gonic/gin"
	"github.com/psychedelicnekopunch/go-sample/app/interfaces/controllers"
)

type Routing struct {
	Gin *gin.Engine
	Port string
	AbsolutePath string
}

func NewRouting() *Routing {
	c := NewConfig()
	r := &Routing{
		Gin: gin.Default(),
		Port: ":8080",
		AbsolutePath: "/var/www/html/go-sample",
	}
	r.loadTemplates()
	r.setRouting()
	return r
}

func (r *Routing) loadTemplates() {
	r.Gin.LoadHTMLFiles(
		r.AbsolutePath + "/app/interfaces/presenters/cookies/index.tmpl",
	)
}

func (r *Routing) setRouting() {
	cookiesController := controllers.NewCookiesController()

	r.Gin.GET("/cookies", func (c *gin.Context) { cookiesController.Get(c) })
	r.Gin.POST("/cookies", func (c *gin.Context) { cookiesController.Post(c) })
}

func (r *Routing) Run() {
	r.Gin.Run(r.Port)
}

/app/interfaces/controllers/Context.go


package controllers

type Context interface {
	Cookie(name string) (string, error)
	HTML(code int, name string, obj interface{})
	SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
	ShouldBind(obj interface{}) error
}

/app/interfaces/controllers/CookiesController.go


package controllers

import (
	"github.com/psychedelicnekopunch/gin-clean-architecture/app/usecase"
)

type CookiesController struct {
	Interactor usecase.CookieInteractor
}

func NewCookiesController() *CookiesController {
	return &CookiesController{
		Interactor: usecase.CookieInteractor{},
	}
}

func (controller *CookiesController) Get(c Context) {
	cookie, _ := c.Cookie("value")
	response, res := controller.Interactor.Get(cookie)
	c.HTML(res.StatusCode, "cookies/index.tmpl", response)
}

func (controller *CookiesController) Post(c Context) {
	cookie, _ := c.Cookie("value")
	var params usecase.CookieParameters
	c.ShouldBind(&params)
	response, res := controller.Interactor.Post(cookie, params)

	if res.Error == nil {
		c.SetCookie("value", response.CookieValue, 60*60*24*365, "/", "", false, true)
	}

	c.HTML(res.StatusCode, "cookies/index.tmpl", response)
}

/app/usecase/CookieInteractor.go


package usecase

import (
	"errors"
)

type CookieInteractor struct {}

type CookieResponse struct {
	CookieValue string
	Forms CookieParameters
}

type CookieParameters struct {
	Value string `form:"value"`
}

func (interactor *CookieInteractor) Get(cookie string) (response CookieResponse, resultStatus *ResultStatus) {
	response.CookieValue = cookie
	return response, NewResultStatus(200, nil)
}

func (interactor *CookieInteractor) Post(cookie string, params CookieParameters) (response CookieResponse, resultStatus *ResultStatus) {
	response.CookieValue = cookie
	response.Forms = params
	if response.Forms.Value == "" {
		return response, NewResultStatus(400, errors.New("value is empty"))
	}
	response.CookieValue = response.Forms.Value
	return response, NewResultStatus(200, nil)
}

/app/interfaces/presenters/cookies/index.tmpl

{{ define "cookies/index.tmpl" }}

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>psychedelicnekopunch/gin-clean-architecture</title>
</head>
<body>
	<a href="/">← top</a><br>

	cookies/index<br>

	<form action="" method="POST">
		<input type="text" name="value" value="{{ .Forms.Value }}" placeholder="name is value"><br>
		<button type="submit">submit</button>
	</form>

	<hr>

	Cookie: {{ .CookieValue }}

</body>
</html>

{{ end }}