IDE : Goland(고랜드)
<Tucker의 Go 언어 프로그래밍>이라는 책을 참고해 Go 언어로 웹 서버를 만들어보려 한다. (웹에 대한 기본 지식을 전제함)
책에는 Gin 프레임워크에 대한 내용은 없어서 따로 찾아보면서 진행했다.
(REST API in Golang using Gin Gonic : https://www.youtube.com/playlist?list=PL8-bdB4cHmXynirCIPtW0G5mCnaoMfr5u)
00. Gin 패키지 설치
go get -u github.com/gin-gonic/gin
01. Gin으로 API 서버 만들기
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default() // default settings
r.GET("", func(c *gin.Context) {
c.String(http.StatusOK, "hello world!") // 1: http status, 2: 응답으로 보내고 싶은 데이터
}) // 1: url, 2: handler function
r.Run("localhost:8080") // api를 호스트할 url과 포트번호
}
gin.Deafult() 함수로 Gin 엔진을 만들 수 있다. 만약 로거가 없는 엔진을 사용하고 싶다면 New() 함수를 사용한다.
위 결과를 실행해보면 아래의 결과를 확인할 수 있다.
만약 JSON 형식을 보내고 싶다면 gin.H를 이용해 map 형식으로 보내주면 된다.
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default() // default settings
r.GET("", func(c *gin.Context) {
c.JSONP(http.StatusOK, gin.H{
"responsibleData":"hello world!",
}) // gin.H{} : map you can configure
}) // 1: url, 2: handler function
r.Run("localhost:8080") // api를 호스트할 url과 포트번호
}
위의 결과를 웹브라우저에서 실행해도 되지만 더 정확한 결과를 확인해보고 싶다면 Postman 등의 툴을 사용하는 것이 더 좋다.
02. HTTP 파라미터 받기
main 함수에 아래 내용도 추가해준다.
r.GET("/:name", func(c *gin.Context){ // :은 gin에게 url 이후에 오는 것이 name 변수로 받아진다는 것
var val = c.Param("name") // 파라미터 name의 값을 변수 val의 값으로 초기화
c.JSON(http.StatusOK, gin.H{
"value":val,
})
})
로그에도 잘 들어와 있다.
url 뒤 파라미터로 들어가는 문자열은 공백도 허용된다. (하지만 파라미터에 /가 들어가면 404 에러가 발생하거나 원하는 결과가 나오지 않을 수 있다.)
03. Body로 들어오는 요청 처리
Body로 들어오는 요청을 처리하기 위해 모델 struct를 만들어준다.
type TestModel struct {
Id int `json:"id" binding:"required"`
Name string `json:"name" binding:"required"`
}
id와 name 값이 optional 하다면 binding을 빼주어도 되지만 필수라면 위처럼 binding:"required"를 추가해주면 된다.
위의 TestModel struct로 body 값을 파싱하려면 아래처럼 하면 된다.
r.POST("/add", func(c *gin.Context) {
var req = &Bind{}
var data TestModel
if err := c.ShouldBind(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error":fmt.Sprintf("%v", err),
})
} else {
c.JSON(http.StatusOK, gin.H{
"data":data,
})
}
})
Bind()나 shouldBind()를 통해 binding:"required"와 같이 처리한 키의 값이 안들어올 시 400 에러가 바로 처리된다.
위 코드에서 if문의 err 처리 부분이 없다면 TestModel에 값이 안 들어와도 통과되어 200이 나게 된다.
ShouldBind() + bind:"required"
err 만 return하고 따로 response 까지 날려주진 않는다. error를 처리하는 부분이 없다면 아래의 플로우도 그대로 실행하게 된다.
Bind() + binding:"required"
400 에러가 바로 난다.
ShouldBind()나 Bind()만 있을 때
에러가 잡히지 않는다.
위 실행 결과에 대한 로그가 찍혀있다.
추가로 param과 query 모두 파싱할 경우는 아래처럼 한다.
Param
애초에 path에 있는 값이라 값이 비어있으면 다른 path로 인식하기 때문에 binding의 필요성이 불분명하다.
type Bind struct {
Name string `uri:"name" binding:"required"`
}
r.POST("/:name", func(c *gin.Context) {
req := &Bind{}
err := c.BindUri(req)
if err != nil
c.JSON(http.StatusBadRequest, err.Error())
return
}
c.Status(http.StatusOK)
})
Query
key는 있어도 값을 주지 않으면 binding:"required"에서 걸리게 된다.
type Bind struct {
Name string `form:"name" binding:"required"`
}
r.POST("/:name", func(c *gin.Context) {
req := &Bind{}
err := c.BindQuery(req)
if err != nil
c.JSON(http.StatusBadRequest, err.Error())
return
}
c.Status(http.StatusOK)
})
(이 부분 출처 : https://genius-kim-1047.tistory.com/59 )
전체 코드
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
type TestModel struct {
Id int `json:"id" binding:"required"`
Name string `json:"name" binding:"required"`
}
func main() {
r := gin.Default() // default settings
r.GET("", func(c *gin.Context) {
c.JSONP(http.StatusOK, gin.H{
"responsibleData": "hello world!",
}) // gin.H{} : map you can configure
//c.String(http.StatusOK, "hello world!") // 1: http status, 2: 응답으로 보내고 싶은 데이터
}) // 1: url, 2: handler function
r.GET("/:name", func(c *gin.Context) { // :은 gin에게 url 이후에 오는 것이 name 변수로 받아진 다는 것
var val = c.Param("name") // 파라미터 name의 값을 변수 val의 값으로 초기화
c.JSON(http.StatusOK, gin.H{
"value": val,
})
})
r.POST("/add", func(c *gin.Context) {
var data TestModel
if err := c.ShouldBind(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": fmt.Sprintf("%v", err),
})
} else {
c.JSON(http.StatusOK, gin.H{
"data": data,
})
}
})
r.Run("localhost:8080") // api를 호스트할 url과 포트번호
}
'Go' 카테고리의 다른 글
[Go] 인터페이스(Interface) (0) | 2022.03.05 |
---|---|
[go/gin/gorm] Basic REST API 만들기 튜토리얼 (4) (0) | 2021.12.21 |
[go/gin] Basic REST API 만들기 튜토리얼 (3) (0) | 2021.12.18 |
[go/gin] Basic REST API 만들기 튜토리얼 (2) : 데이터 바인딩 (0) | 2021.12.16 |
<Tucker의 Go 언어 프로그래밍> Done 리스트 (1회독) (0) | 2021.12.15 |