먼저 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
}