먼저 Go server.go 파일을 메인파일로 생성한다.
server.go는 Url과 컨트롤러 사이의 매핑관계이다.
package main
import (
"controller"
"entity"
"fmt"
"github.com/gin-gonic/gin"
"io"
"middlewares"
"net/http"
"os"
"service"
)
var (
videoService service.VideoService = service.New()
videoController controller.VideoController = controller.New(videoService)
)
func setupLogOutput() {
f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
}
func main() {
//MiddleWares쪽의 로그 파일
setupLogOutput()
//서버를 생성한다.
server := gin.New()
//서버에서 사용할 middlewares 이 파일은 생성 후 실행된다.
server.Use(gin.Recovery(), middlewares.Logger(), middlewares.BasicAuth())
//비디오 정보를 알려올 페이지 이다.
//GET요청이고 첫번째 파라미터로 매칭할 url의 주소를 입력한다
//두번째 파라미터로는 Context로 받아와 body header등을 불러와 요청 작업을 처리한다.
server.GET("/video", func(context *gin.Context) {
context.JSON(200, gin.H{"test": "Test"})
})
//비디오 의 모든 정보를 JSON파일로 리턴한다.
server.GET("/videos", func(context *gin.Context) {
var videos []entity.Video
videos = videoController.FindAll()
context.JSON(http.StatusOK, videos)
})
//:id로 url 파라미터를 받아 올 수 있다. context.Param("id")
server.GET("/video/:id", func(context *gin.Context) {
var video entity.Video
video = videoController.GetVideo(context)
context.JSON(http.StatusOK, video)
})
//비디오를 추가 시킨다.
server.POST("/video", func(context *gin.Context) {
err := videoController.Save(context)
if err != nil {
context.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
} else {
//200요청이 들어왔다면 메세지를 출력한다.
context.JSON(http.StatusOK, gin.H{"message": "Video Input Ok"})
}
})
//DELETE요청 :id의 값의 테이블을 삭제 시킨다.
server.DELETE("/video/:id", func(context *gin.Context) {
err := videoController.Delete(context)
if err != nil {
fmt.Println(err)
context.JSON(http.StatusOK, gin.H{"Error": "error"})
}
})
//PUT요청 :id의 값을 수정한다.
server.PUT("/video/:id", func(context *gin.Context) {
videoController.FixVideo(context)
context.JSON(http.StatusOK, gin.H{
"Update": "success",
})
})
//어디 서버의 포트로 연결 시킬지 매핑한다.
server.Run(":8001")
}
Controller
controller 경로를 생성 뒤 View - Controller - Serivce 와 매핑할 video-controller를 생성한다.
package controller
import (
"entity"
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator"
"service"
"strconv"
"validators"
)
//View와는 인터페이스로 소통한다.
type VideoController interface {
FindAll() []entity.Video
Save(ctx *gin.Context) error
Delete(ctx *gin.Context) error
GetVideo(ctx *gin.Context) entity.Video
FixVideo(ctx *gin.Context) entity.Video
}
//Controller에서 사용할 서비스 구조체를 생성한다.
type controller struct {
service service.VideoService
}
// 유효성 검사를 위해 생성한다.
var validate *validator.Validate
//New 메서드로 외부에서 사용할수 있게 한다.
//service를 매개변수로 받고 controller의 service에 매핑시킨다.
//controller.service로 서비스와의 통신이 가능해졌다.
//서비스 구조체는 주소값으로 받아 하나의 객체만 생성한다.
//*를 쓰면 주소값으로 받아와 리턴하므로 service가 복사되지 않고 객체 안에서는 유지된다.
func New(service *service.VideoService) VideoController {
validate = validator.New()
validate.RegisterValidation("is-cool", validators.ValidateCoolTitle)
return controller{
service: *service,
}
}
//Update문
//reciver로 Controller를 받고 controller의 메서드를 생성한다.
func (c controller) FixVideo(ctx *gin.Context) entity.Video {
//비디오 Entity객체를 생성한다.
var video entity.Video
//들어온 값을 BindJSON으로 매핑한다.
//주소값으로 매핑하므로 video의 객체에 바인드된다.
err := ctx.BindJSON(&video)
if err != nil {
fmt.Println(err.Error(), "Controller Bad")
}
//:id의 값을 컨텍스트에서 받아온다.
id, err := strconv.Atoi(ctx.Param("id"))
if err != nil {
fmt.Println(err.Error())
}
//controller의 변수인 service를 호출하여 비지니스 로직을 처리한다.
changeVideo := c.service.Update(video, id)
//entity값을 리턴한다.
return changeVideo
}
//하나의 비디오 정보를 가져온다.
func (c controller) GetVideo(ctx *gin.Context) entity.Video {
//id의 값을 가져온다.
id, err := strconv.Atoi(ctx.Param("id"))
//비디오 객체를 생성한다.
var video entity.Video
if err != nil {
fmt.Println(err.Error())
} else {
//서비스로직을 처리한다.
video = c.service.GetVideo(id)
}
return video
}
//DELETE :id값을 받아온다. GetVideo와 비슷하다.
func (c controller) Delete(ctx *gin.Context) error {
id, err := strconv.Atoi(ctx.Param("id"))
if err != nil {
return err
}
//Delete 서비스를 호출한다.
c.service.Delete(id)
return nil
}
//FindAll로 모든 데이터를 가져온다.
func (c controller) FindAll() []entity.Video {
return c.service.FindAll()
}
//Save로 데이터를 저장한다.
func (c controller) Save(ctx *gin.Context) error {
//video entity를 생성한다.
var video entity.Video
//validation에 저장된 로직을확인후 video에 매핑한다.
err := ctx.ShouldBindJSON(&video)
if err != nil {
return err
}
err = validate.Struct(video)
if err != nil {
return err
}
c.service.Save(video)
return nil
}
service
Controller에 값을 Response하고 db와 통신하고 서비스 로직을 처리한다.
인터페이스로 생성뒤 처리한다.
통신해야할 객체가 db이므로 db를 주입시켜주어야한다.
service 경로를 생성 뒤
service-video로 go파일을 생성한다.
package service
import (
"entity"
"repository"
)
//외부에서 사용할 인터페이스이다.
type VideoService interface {
Save(video entity.Video) entity.Video
FindAll() []entity.Video
Delete(id int)
Update(video entity.Video, id int) entity.Video
GetVideo(id int) entity.Video
}
//의존성을 주입할 생성자이다.
type videoService struct {
db repository.VideoRepository
}
//생성이 되게되면 videoService의 주소값을 매핑하여 하나만 생성하게된다.
//db에는 우리가 사용할 db interface 매핑시킨다.
func New() VideoService {
return &videoService{
db: repository.NewVideoRepository(),
}
}
//Getvideo를 구현했다.
func (service *videoService) GetVideo(id int) entity.Video {
return service.db.GetVideo(id)
}
//Delete를 구현했다.
func (service *videoService) Delete(id int) {
service.db.Delete(id)
}
//Update를 구현했다.
func (service *videoService) Update(video entity.Video, id int) entity.Video {
return service.db.Update(video, id)
}
//Save를 구현 했다.
func (service *videoService) Save(video entity.Video) entity.Video {
return service.db.Save(video)
}
func (service *videoService) FindAll() []entity.Video {
entity := service.db.FindAll()
return entity
}