golang - WebFramework gin
아래 글은 golang을 공부할 목적으로 웹에서 본 글들을 정리한 것이다.
개요
설치
go get github.com/gin-gonic/gin
hello World
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 1. http://localhost:8080/ 에 접근하면 「Hello world」라고 표시한다.
r.GET("/", func(c *gin.Context) {
c.String(200, "Hello world")
})
//2. http://localhost:8080/hoge 에 접근하면 「fuga」 라고 표시한다.
r.GET("/hoge", func(c *gin.Context) {
c.String(200, "fuga")
})
r.Run(":8080")
}
package main
import (
"os"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(200, "hello")
})
port := os.Getenv("PORT")
if len(port) == 0 {
port = "3000"
}
r.Run(":" + port)
}
샘플 코드
package controllers
import (
"bookshelf/models"
)
// User is
type User struct {
}
// NewUser ...
func NewUser() User {
return User{}
}
// Get ...
func (c User) Get(n int) interface{} {
repo := models.NewUserRepository()
user := repo.GetByID(n)
return user
}
package main
import (
"bookshelf/controllers"
"github.com/gin-gonic/gin"
"reflect"
"strconv"
)
func main() {
router := gin.Default()
router.GET("/:id", func(c *gin.Context) {
// Pram을 처리한다
n := c.Param("id")
id, err := strconv.Atoi(n)
if err != nil {
c.JSON(400, err)
return
}
if id <= 0 {
c.JSON(400, gin.H{"status": "id should be bigger than 0"})
return
}
// 데이터를 처리한다
ctrl := controllers.NewUser()
result := ctrl.Get(id)
if result == nil || reflect.ValueOf(result).IsNil() {
c.JSON(404, gin.H{})
return
}
c.JSON(200, result)
})
router.Run(":8080")
}
http://localhost:8080/[user_id]로 지정한 user_id 유저 정보를 얻는다.
Gin의 Middleware 와 HandlerFunc 에서 데이터 주고 받기
- gin.*Context.Set 과 gin.*Context.Get 으로 동일 리퀘스트에 한해서 데이터를 주고 받는 것이 가능.
- 유저 인증으로 사용하는 예
- Middleware 에서 유저를 인증하고, HandlerFunc에서 인증된 유저를 취득.
package main
import "github.com/gin-gonic/gin"
// Midleware
func AuthRequired() gin.HandlerFunc {
return func(c *gin.Context) {
// Some authorization in Authorization
user := Authorization()
c.Set("AuthorizedUser", user)
}
}
// HandlerFunc
func GetProfile(c *gin.Context) {
user := c.Get("AuthorizedUser")
}
func main() {
r := gin.Default()
r.Use(AuthRequired())
r.GET("/profile", GetProfile)
r.run()
}
미들웨어 바인딩 사용
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
type ContactForm struct {
Name string `form:"name" binding:"required"`
Message string `form:"message" binding:"required"`
}
type ContactJSON struct {
Name string `json:"name" binding:"required"`
Message string `json:"message" binding:"required"`
}
func main() {
router := gin.Default()
router.POST("/", func(c *gin.Context) {
var form ContactForm
c.BindWith(&form, binding.Form)
c.String(200, "Name: " + form.Name + "\nMessage: " + form.Message + "\n")
})
router.POST("/json", func(c *gin.Context) {
var json ContactJSON
c.BindWith(&json, binding.JSON)
c.String(200, "Name: " + json.Name + "\nMessage: " + json.Message + "\n")
})
router.Run(":3000")
}
ttp localhost:3000 name=foo message=bar http localhost:3000/json name=foo message=bar
Binding&Validation
type TestForm struct {
Name string `json:"name" binding:"required"`
Text string `json:"text" binding:"required,max=1000"`
}
- 우선 Form을 저장하는 구조체를 정의하고 태그에 Binding용 정의와 Validation용 정의를 쓴다.
- Binding 태그 안에 실시하는 Validation을 열거한다. 여러 개 있을 경우 컴마 단락으로 쓰다.
- 평가는 왼쪽에서 차례대로, Error가 있을 경우 이후의 평가는 하지 않는다.
- 이용할 수 있는 Validation은 이곳을 참조
- 아래 json 데이터를 보낸다고 가정
{"name": "taro", "text": "hogehoge"}
r.POST("/test", func(c *gin.Context) {
var form TestForm
c.Bind(&form)
log.Println(form.Name) // taro
log.Println(form.Text) // hogehoge
...
- HandlerFunc 중에서 정의한 Form 구조체를 선언하고, gin.Context의 Bind 메서드에 포인터를 주면 좋게 Binding 해준다.
r.POST("/test", func(c *gin.Context) {
var form TestForm
if err := c.Bind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": "BadRequest"})
return
}
// 이하 정상 처리
- 에러 상세 처리
r.POST("/test", func(c *gin.Context) {
var form TestForm
if err := c.Bind(&form); err != nil {
errors := err.(*validator.StructErrors)
log.Println("Struct:", errors.Struct)
for k, v := range errors.Errors {
log.Println("Key:", k)
log.Println("Field:", v.Field)
log.Println("Param:", v.Param)
log.Println("Tag:", v.Tag)
log.Println("Kind", v.Kind)
log.Println("Type:", v.Type)
log.Println("Value", v.Value)
log.Println("==========")
}
log.Println(errors.StructErrors)
c.JSON(http.StatusBadRequest, gin.H{"status": "BadRequest"})
return
}
// 아래는 정상 처리
볼 글
이 글은 2018-12-20에 작성되었습니다.