GINフレームワークを用いてgolang/goが開発したフレームワークレス管理バックグラウンドを再構築する

7309 ワード

前提条件
業務上必要なため、ゲームの管理バックグラウンドを開発する必要があり、これまでフロントエンドに接触したことがなく、GOについてのみ比較的浅い理解があったため、GOを使用してバックグラウンドを開発した.
誤導される
私は検索中に誤解されたが、Golangはフレームワークを使わないというネットユーザーの話もある.
确かに、本やネット上のDEMOは简単で、プログラミングの基础がある人にとっては、确かに上手ですが、长期的にバックエンドをしている人にとっては、実は穴があると深く感じません.
開発中に発生した問題
  • コードの構造がはっきりしていないので、中期にチャットルームの開発方法についてのプログラムを学んで、MVCアーキテクチャの使用を思い出しました.
  • コードが重複し、GO思考がなく、多くの重複コードを招いた.
  • 論理混乱、フロントエンドパラメータ処理、Redis/MySQL操作;
  • 多くの原生APIは使い勝手が悪い.

  • 改善を考える
    しばらく忙しくて、やっと暇になって、再び再構築するつもりで、既存のバックグラウンド
    フレーム選択
    しばらく知ってから、beegoフレームワークを使おうとしたが、比較的小さなプロジェクトでDEMOをテストしてみると、いくつかの小さな問題が発見された.beegoには使いやすい機能がたくさんパッケージされているが、使用者にとっては、プロファイル、ログファイルなど、良いことではない場合がある.beegoを使おうとすると、既存の変動が大きい
    Golang交流の中で群の中でみんなに教えてもらって、みんなはすべてGINを使うことを提案して、beegoではありませんて、GINを選んで再構築して、2日もかからないで、GINフレームワークを使って私のすべてのコードを再構築して、総コード量(Golang:2万JS:2万)
    GIN使用後のまとめ
    パラメータの入手が容易
    イニシャルコード
    func Processer(w http.ResponseWriter, r *http.Request) {
        r.ParseForm() //   ,      ,       name
        fmt.Println(r.Form.Get("name"))
    }
    

    GINフレームを使用した後
    func Processer(c *gin.Context) {
        fmt.Println(r.Query("name")) //GET name
        fmt.Println(r.DefaultQuery("name", "Roger")) //GET name        
        fmt.Println(r.PostForm("name")) //POST name
        fmt.Println(r.DefaultPostForm("name", "luojie")) //POST name        
    }
    

    GINフレームワークはGETとPOSTに違いがあるが,便利さにはデフォルトパラメータが追加され,開発者にはGETとPOSTを明確に認識することが要求される.
    ファイルアップロード専用パッケージ
    func uploadConfig(w http.ResponseWriter, r *http.Request) {
    		file, handler, err := r.FormFile("uploadfile")
    		if err != nil {
    			log.Println("form file err: ", err)
    			//fmt.Fprintf(w, "        ")
    			return
    		}
    		defer file.Close()
    		fmt.Fprintf(w, "%v", handler.Header)
    		//         
    		f, err := os.OpenFile("./files/"+handler.Filename, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
    		if err != nil {
    			log.Println("open file err: ", err)
    			fmt.Fprintf(w, "      ")
    			return
    		}
    
    		defer f.Close()
    		//    
    		io.Copy(f, file)
    		//  
    }
    

    GINフレーム
        router.POST("/upload", func(c *gin.Context) {
            //    
            file, _ := c.FormFile("file")
            log.Println(file.Filename)
    
            //           
            c.SaveUploadedFile(file, dst)
            //  
        })
    

    明らかにコードは簡単で、ファイルのアップロードに対して、もうプレッシャーを感じません.GINは私たちのエラーの確率を大幅に簡略化したからです.
    ルーティンググループ
    元のコード
    type MyServeMux struct{}
    
    func (mux *MyServeMux) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
        pattern = "/v1" + pattern
        http.DefaultServeMux.HandleFunc(pattern, handler)
    }
    
    func main() {
        mux := &MyServeMux{}
        mux.HandleFunc("/login", loginEndpoint)
        mux.HandleFunc("/submit", submitEndpoint)
        mux.HandleFunc("/read", readEndpoint)
    }
    

    GINフレーム
    func main() {
        router := gin.Default()
    
        // Simple group: v1
        v1 := router.Group("/v1")
        {
            v1.POST("/login", loginEndpoint)
            v1.POST("/submit", submitEndpoint)
            v1.POST("/read", readEndpoint)
        }
    }
    

    開発者、注目すべきものはもっと少ない.
    ミドルウェア権限の検証に使用
    元のコード
    func (mux *MyServeMux) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
        pattern = "/v1" + pattern
        http.DefaultServeMux.HandleFunc(pattern, handler)
    }
    
    func (mux *MyServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        //         http.DefaultServeMux.ServeHTTP(w, r)
        //     return
    }
    
    func main() {
        mux := &MyServeMux{}
        mux.HandleFunc("/login", loginEndpoint)
        mux.HandleFunc("/submit", submitEndpoint)
        mux.HandleFunc("/read", readEndpoint)
    }
    

    GINフレーム
    func main() {
        router := gin.Default()
    
        // Simple group: v1
        v1 := router.Group("/v1", checkAuth)
        {
            v1.POST("/login", loginEndpoint)
            v1.POST("/submit", submitEndpoint)
            v1.POST("/read", readEndpoint)
        }
    }
    
    func checkAuth(c *gin.Context) {
        //       c.Next()
        //       c.Abort()
    }
    

    便利さは前条と一致する
    パラメータバインド、符号化効率の向上
    パラメータバインドがない前に
    func RechargeMakeUp(w http.ResponseWriter, r *http.Request) {
        ip := util.GetRequestIP(r)
        requestData := &model.WebRechargeMakeup{ActUserName: actUserName, ActIP: ip} 
    
        data, err := ioutil.ReadAll(r.Body)                                    
        if err != nil {
            logger.Logger.Errorf("request data error")
            util.SetErrorAjaxResponse(w, err)
            return
        } else {
            logger.Logger.Debugf("data[%s]", string(data))
            if err := json.Unmarshal(data, requestData); err != nil {
                logger.Logger.Errorf("json Unmarshal error")
                util.SetErrorAjaxResponse(w, err)
                return
            }
            //....
        }
    }
    

    バインド後
    func RechargeMakeUp(c *gin.Context) { 
        ip := model.GetRequestIP(c.Request)
        requestData := &model.WebRechargeMakeup{ActUserName: actUserName, ActIP: ip} 
        if err := c.ShouldBindJSON(requestData); err != nil {
            model.Logger.Errorf("json Unmarshal error")
            model.SetErrorAjaxResponse(c, err)
            return
        }
        //...
    }
    

    コードを大幅に削減し、生産性を向上
    静的ファイルの設定をより簡単に
    元の静的ファイル設計
    func main() {
        http.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir("static"))))
    }
    

    GINフレーム
    func main() {
        r := gin.Default()
        r.Static(/static/, "./static")
    }
    

    道理を言って、前の設計はあまりにも反人類で、私はかつてこの中で、卵は長い間かわいがって、やっと正常に静的なディレクトリを正常に配置して、GINのフレームワークの中で簡単に明らかにしました
    もっと豊かに
    元のコード
    func process(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "%s",  "

    Hello World!

    ") // fmt.Fprintf(w, "{"message":"hello world"}") // JSON fmt.Fprintf(w, "/static/login.data") // // , }

    GINフレーム
    func process(c *gin.Context) {
        c.HTML(http.StatusOK, "hello.html", nil) //    
        c.JSON(http.StatusOK, gin.H{"message":"Hello World!"}) //  JSON
        c.String(http.StatusOK, "Hello World!") //     
        c.File("/static/login.data") //    
        //...     
    }
    
    

    このような豊かな戻りが大好きで、以前の痛みは多くのAjaxの戻りがJSを使っていたことにあります.戻りごとに手動で文字列に変換して返さなければなりません.汎用戻りを直接書いてinterfaceを文字列に変えることができますが、それに対応する思考が欠けています.新しいフレームワークを絶えず理解する過程で、自分の認識を絶えず改善することができます.こんな感じで素敵
    より良いテンプレートサポート
    func formatAsDate(t time.Time) string {
        year, month, day := t.Date()
        return fmt.Sprintf("%d%02d/%02d", year, month, day)
    }
    
    func main() {
        r := gin.Default()
        r.Delims("{[{", "}]}") //          
        r.SetFuncMap(template.FuncMap{
            "formatAsDate": formatAsDate,
        }) //      
    	r.LoadHTMLGlob("./view/**/*") //           ,       ,      
    }
    

    その他の使いやすい機能
    現在、GINフレームワークの他の使いやすい機能については、まだ探求が続いています.