echo에서 golang의 REST API 구현 구성

18543 단어 Goecho

입문


웹 서비스 개발 & & REST API 학습에서 golang의 echo를 사용했지만 API 규격으로 각 URL+ 방법마다 함수를 등록할 수 있기 때문에 REST API와의 상성은 좋지 않습니까.
regist_api.go
group := e.Group("/api/")
group.GET(uri, get_handler_fnc)
group.POST(uri, post_handler_fnc)
group.PUT(uri, put_handler_fnc)
group.DELETE(uri, delete_handler_fnc)
그러나 이런 함수 로그인계의 API는 아무 것도 고려하지 않고 하면 함수의 양이 심해지기 때문에 팀 간에 API의 규격을 조정하면서 개발하면 상당히 혼란스러워진다.
그래서 어느 정도 통용되는 형태로 설치를 시도했다.

설계


기본 방침은 이렇게 고려한 것이다.
  • GET/POST/PUT/DELETE는 각 URI의 HandleXXX에 설치됩니다
  • HandleXXX의 실체는 Factoryclass의 실체가 되고main처리에 의존하지 않는다
  • 1과 2를 연결하는 인터페이스를 정의합니다
  • 3의 정의는 echo의 처리를 이용하여 필요한 것만 실시하고 로그인할 수 있으며 GET/POST/POT/DELETE의 기본 함수를 준비하여 필요에 따라 오버라이드를 할 수 있다.
    클래스는 전자의 그림이다

    서류 구성은 이런 느낌이다.
    main.go
    controller/
     |
     +- handle_xxx.go -- REST APIの実処理はこれで統一
     +- handle_Logout.go
     +- handle_passphrase.go
     +- handle_passphraseInfo.go
     +- handle_userAccount.go
     |
     `- msg_handler.go -- interface, factory classの定義
    

    실시


    에코 처리 형식을 이용하다


    go의 인터페이스 정의는 이렇게 진행된다.
    controller/msg_handler.go
    type Method int
    const (
        METHOD_GET Method = iota
        METHOD_POST
        METHOD_PUT
        METHOD_DELETE
    )
    
    type MsgHandler interface {
        GetHandlerFunc(method Method) echo.HandlerFunc
    }
    
    각 Handle 클래스를 상속하고 생성합니다.정의가 있는지 없는지를 판별하기 위해 약간 우회적으로 설치했다.
    controller/handle_passphraseInfo.go
    //継承用の構造体定義。メンバーが必要なら追加します。
    type HandlePassphraseInfo struct {
    }
    
    //頭にthis *構造体を付けてあげると、構造体がthis参照できます。
    func (this *HandlePassphraseInfo) GetHandlerFunc(method Method) echo.HandlerFunc{
       //実装したメソッドを返してあげる
       switch method {
        case METHOD_GET: return this.get
        case METHOD_PUT: return this.put
        case METHOD_DELETE: return this.deleteMethod
        default: return nil
        }
    }
    
    //bodyがJSONフォーマットなら、c.JSON(ステータスコード, res)で応答
    func (this *HandlePassphraseInfo) get(c echo.Context) error {
        /*実処理*/
        return c.JSON(http.StatusOK, res)
    }
    
    //他のメソッドも同じような感じで定義
    
    factory에서 위에서 말한 바와 같이 실현된handle을 생성합니다.
    controller/msg_handler.go
    func MsgHandlerFactory() map[string]MsgHandler {
        var results map[string]MsgHandler = map[string]MsgHandler{"passphrase":&HandlePassphrase{}, "passphraseInfo":&HandlePassphraseInfo{}, "userAccount":&HandleUserAccount{}, "logout":&HandleLogout{}}
        return results
    }
    
    마지막으로 메인으로 등록합니다.
    main.go
        e = echo.New()
    
        // regist handler
        group := e.Group("/api/")
        msg_handler := controller.MsgHandlerFactory()
        for uri, instance := range msg_handler {
            //Set method GET
            if handler_fnc := controller.GetEchoHandler(instance, controller.METHOD_GET); handler_fnc != nil {
                group.GET(uri, handler_fnc)
            }
    
            if handler_fnc := controller.GetEchoHandler(instance, controller.METHOD_POST); handler_fnc != nil {
                group.POST(uri, handler_fnc)
            }
    
            if handler_fnc := controller.GetEchoHandler(instance, controller.METHOD_PUT); handler_fnc != nil {
                group.PUT(uri, handler_fnc)
            }
    
            if handler_fnc := controller.GetEchoHandler(instance, controller.METHOD_DELETE); handler_fnc != nil {
                group.DELETE(uri, handler_fnc)
            }
        }
    

    오버라이드 형식


    인터페이스 정의가 조금 늘었지만 다른 코드도 시원해집니다.
    인터페이스는 이런 느낌이에요.GetHandlerFunc 필요 없어요.
    controller/msg_handler.go
    type MsgHandlerIf interface {
        Get(c echo.Context) error
        Post(c echo.Context) error
        Put(c echo.Context) error
        Delete(c echo.Context) error
    }
    
    type MsgHandler struct {
    }
    func (this MsgHandler) Get(c echo.Context) error {return c.NoContent(http.StatusMethodNotAllowed)}
    func (this MsgHandler) Put(c echo.Context) error {return c.NoContent(http.StatusMethodNotAllowed)}
    func (this MsgHandler) Post(c echo.Context) error {return c.NoContent(http.StatusMethodNotAllowed)}
    func (this MsgHandler) Delete(c echo.Context) error {return c.NoContent(http.StatusMethodNotAllowed)}
    
    //return: map[uri]MsgHandler
    func MsgHandlerFactory() map[string]MsgHandlerIf {
        var results map[string]MsgHandlerIf = map[string]MsgHandlerIf{"passphrase":&HandlePassphrase{}, "passphraseInfo":&HandlePassphraseInfo{}, "userAccount":&HandleUserAccount{}, "logout":&HandleLogout{}}
        return results
    }
    
    계승용 코드는 구조의 시작에 부대를 기록한다.이후 echo 처리 형식으로 설치된 get/post/put/delete를 Get/Post/Put/Delete로 변경하면 됩니다.
    handle_passphraseInfo.go
    type HandlePassphraseInfo struct {
        MsgHandler
    }
    
    그리고 메인.아주 시원해요.
    main.go
        e = echo.New()
    
        // regist handler
        group := e.Group("/api/")
        msg_handler := controller.MsgHandlerFactory()
        for uri, instance := range msg_handler {
            group.GET(uri, instance.Get)
            group.POST(uri, instance.Post)
            group.PUT(uri, instance.Put)
            group.DELETE(uri, instance.Delete)
        }
    

    좋은 웹페이지 즐겨찾기