Using go language to build a Web Application Tutorial

Time:2021-6-30

1.Abstract

In the process of learning web development, we will encounter many difficulties, so I wrote a similar review article. As a roadmap, starting from the index of web development elements, this paper introduces the learning process and example code of golang development.

In the description, the code is mostly used to describe the use method, not too much description. Finally, you can easily copy the code to achieve their own needs.

The subjects of this paper are as follows

  • Someone who has some experience in web development
  • People who can use ajax flexibly (at least know how to separate front and back)
  • Have a certain understanding of golang web development, at least skim some books on golang web development

After reading this article, you will get:

  • Some skills of developing golang Web
  • Some practical APIs for golang web development

In this paper, in order to explain as detailed as possible, the explanation has been written into the code comments.
2. Golang web development checklist

Omitted part: basic process control, OOP and other basic grammar knowledge.

3. Router

Router is the soul of the whole website, if the routing is not good, URL will be very disgusting. So this part is designed to be the first one.

There are two kinds of routing, one is manual routing, in order to schedule fixed functions through TUL, and the other is resource acquisition, which imitates the way of static page to obtain resources through URL analysis (similar to get)

Automatic routing, mainly using OOP command mode to achieve. All functions use post, unified entrance, convenient authority management, security management, cross domain management. But it’s better to leave such powerful functions to the framework. Here is no reference for novices.

3.1 manual routing

   

Copy codeThe code is as follows:
package main
    import (
      “log”
      “net/http”
      )
      func main() {
        Routerbinding() / / route binding function
        Err: = http.listenandserve (“: 9090”, Nil) / / set listening port
        if err != nil {
          log.Fatal(“ListenAndServe: “, err)
        }
      }

Bind route before running httpserver
3.2 binding of manual routing
3.2.1 static files

   

Copy codeThe code is as follows:
http.Handle(“/pages/”, http.StripPrefix(“/pages/”, http.FileServer(http.Dir(“./pages”))))

3.2.2 fixed function and resource acquisition

They are all the same

   

Copy codeThe code is as follows:
http.HandleFunc(“/images/”, fileUpload.DownloadPictureAction)

4. Page loading
4.1 pure static page (HTML)

Just give it to the router. Automatically access that folder. However, the production environment really has to be CDN, if you have more servers. You can use nginx reverse proxy.

The main advantage is the separation of the front and back, and the ability to access the CDN means more communication times. But it’s OK to optimize and improve.

4.2 loading template page

   

Copy codeThe code is as follows:
Commonpage, err: = template. Parsefiles (“pages / common / head. Gtpl”, / / load template
    “pages/common/navbar.gtpl”, “pages/common/tail.gtpl”)
    if err != nil {
      panic(err.Error())
    }
    Navargs: = map [string] string {“home”: “home”, “user”: “yupengfei”} / / complex parameters start to be pushed in
    knowledgePage, err := template.ParseFiles(“pages/knowledge/knowledge.gtpl”)
    knowledgeArgs := map[string]interface{}{“Head”: “This is a test title”,
    “Author”: “kun.wang”, “PublishDatetime”: “2014-09-14”,
    ” Content “: template. HTML (” < P style = \ “text indent: 2em \” > why use semantics</ p> “)} / / it’s not bad, but string analysis will affect the efficiency of the project
    Commonpage. Executetemplate (W, “header”, Nil) / / render starts
    commonPage.ExecuteTemplate(w, “navbar”, navArgs)
    knowledgePage.ExecuteTemplate(w, “knowledge”, knowledgeArgs)
    commonPage.ExecuteTemplate(w, “tail”, nil)

Only key codes are provided.

    The others are very good, but the server for page rendering is not too luxurious.
    It is difficult to use string array as input parameter
    Conclusion: Although the number of communication is reduced, but there is no way to CDN egg pain, in addition, the template mapping egg pain.

5. Presentation layer script

Presentation layer scripts are difficult to do and not easy to learn. But once it’s done, the reusability of the code will be greatly improved.

In general, JS development efficiency is very high, flexibility is high, and the use of the client CPU performance is good, free resources, learning people are also more, good recruitment.

5.1 require.js
5.1.1 loading

   

Copy codeThe code is as follows:
<script data-main=”/reqmod/login_main” language=”JavaScript” defer async=”true” src=”js/r.js”></script>

Leave the whole web page as an entry for loading scripts (it’s better to have only one JS file for each page)

benefit

    JS is delay loading. There will be no web page stuck
    Maximize cache usage( HTTP 304)
    A web page uses only one JS
    DOM event binding, no need to write JS binding on HTML control

Disadvantages

    It’s hard to learn
    Website updates always have browsers that are not updated. Cause errors (so in some cases, customers know how to refresh several times, which has become a habit of users)

Parameter interpretation

    ` Data main ‘business logic entry, load the current string. JS file
    ` No explanation
    ` The literal meaning of “defer async”
    ` SRC ` r.js means require.js. Code can be found everywhere.

5.1.2 page

Load dependent files

   

Copy codeThe code is as follows:
require.baseUrl = “/”
    require.config({
      baseUrl: require.baseUrl,
      paths: {
        “jquery”: “js/jquery-1.10.2.min”,
        “domready” : “reqmod/domReady”,
        “pm” : “reqmod/pmodal”,
        “cookie”:”reqmod/cookie”,
        “user”:”reqmod/user”,
        “bootstrap”: “reqmod/bootstrap.min”,
        “nav”:”reqmod/nav”
      },
      shim: {
        ‘bootstrap’: {
          deps: [‘jquery’]
        }
      }
    });
    // Direct copy.

Execute page business

The most important thing to do in execution is to bind DOM to events. Load all kinds of JS libraries and reference them directly.

Beautiful code, development efficiency, execution efficiency are very good.

   

Copy codeThe code is as follows:
require([‘nav’,’domready’, ‘jquery’, ‘user’,’pm’], function (nav,doc, $, user,pm){
      // The first array parameter of this function is the selected dependent module. 1. Website absolute path. 2. Select the content of export when loading dependent module
      // The order of the array should be the same as that of the function. If there are two modules that depend on, for example, the jQuery plug-in, it should be written that in the end, you don’t need variables to use them directly`$`
      doc(function () { // domReady
        pm.load();// Loading various plug-ins, HTML templates and so on are OK
        $(‘# btn_ login’)[0].onclick = function(){user.login();}// Button event binding
      });
    });

Page model

   

Copy codeThe code is as follows:
define([‘jquery’,’reqmod/cookie’,’user’,’bootstrap’],function ($,cookie,user){
        // The parameter content of the define function requires is the same.
        // The dependent module should have path configuration in the module calling this module. Otherwise, they will die miserably. When they report mistakes, they will not say that there is something wrong.
      var nav_ Load = function () {/ / just copy the function definition
        $.get(‘/nav.html’, function(result){
          var newNode = document.createElement(“div”);
          newNode.innerHTML = result;
          $(‘body’)[0].insertBefore(newNode,$(‘body’)[0].firstChild);
          //document.body.innerHTML = result + document.body.innerHTML;
          $(‘#btn_login’)[0].onclick = function(){user.login();}
          $(‘#btn_reg’)[0].onclick = function(){window.location=’/register.html’}
          $.post(‘/login_check’,{},function(data){
            if(data==0){
              Form_login.style.display=””
            }
            else{
              form_userInfo.style.display=””
            }
          })
        });
      }
      Return {/ / this is similar to micro routing. Very flexible, very convenient
        load :nav_load
      };
    });

5.2 JQuery

The functions of JQ are basically the same as long as require. JS is referenced.

If necessary, you can go to w3school to learn.

6. Business layer

Post analysis

   

Copy codeThe code is as follows:
func XXXAction(w http.ResponseWriter, r *http.Request) {
      r. Parseform() / / only with this can I get the parameter
      r. Form [“email”] / / get email parameters (string)
      // Write the next business.
    }

Resource entry function resource require analysis (URL analysis fixed writing)

   

Copy codeThe code is as follows:
func Foo(w http.ResponseWriter, r *http.Request) {
      queryFile := strings.Split(r.URL.Path, “/”)
      Queryresource: = queryfile [len (queryfile) – 1] / / parse file
    }
    // After the completion of string segmentation, according to the requirements to obtain resources.

Input object directly

   

Copy codeThe code is as follows:
Data, err: = ioutil. Readall (r.body) / / read form as JSON string directly
     if err != nil {
      utility.SimpleFeedBack(w, 10, “failed to read body”)
      pillarsLog.PillarsLogger.Print(“failed to read body”)
      return
     }
     k := 【BUSINESS OBJECT】
     err = json.Unmarshal(data, &k)
     if err != nil {
      utility.SimpleFeedBack(w, 13, “Pramaters failed!”)
      pillarsLog.PillarsLogger.Print(“Pramaters failed!”)
      return
     }
    // Convenient and fast. When accessing parameters again, you can call structure parameters directly.
    // Note that Ajax needs to make some adjustments when calling functions, and the code is as follows:
    $. ajax([dist],JSON.stringify([data]),function(){},’json’);// Pay attention to JSON

7. Persistence layer
7.1 Mysql

In fact, the MySQL driver of any language comes from pro * C, so it’s easy to say anything after pro * C

Insert/Delete/Update

   

Copy codeThe code is as follows:
stmt, err := mysqlUtility.DBConn.Prepare(“INSERT INTO credit (credit_code, user_code, credit_rank) VALUES (?, ?, ?)”)
    if err != nil {
      pillarsLog.PillarsLogger.Print(err.Error())
      return false, err
    }
    defer stmt.Close()
    _, err = stmt.Exec(credit.CreditCode, credit.UserCode, credit.CreditRank)
    if err  != nil {
      return false, err
      } else {
        return true, err
      }
      // It’s more convenient

Query

   

Copy codeThe code is as follows:
stmt, err := mysqlUtility.DBConn.Prepare(`SELECT commodity_code, commodity_name, description, picture,
      price, storage, count, status,
      insert_datetime, update_datetime FROM commodity WHERE commodity_code = ?`)
      if err != nil {
        return nil, err
      }
      defer stmt.Close()
      result, err := stmt.Query(commodityCode)
      if err != nil {
        return nil, err
      }
      defer result.Close()
      var commodity utility.Commodity
      if result.Next() {
        err = result.Scan(&(commodity.CommodityCode), &(commodity.CommodityName), &(commodity.Description),
        &(commodity.Picture), &(commodity.Price), &(commodity.Storage), &(commodity.Count), &(commodity.Status),
        &(commodity.InsertDatetime), &(commodity.UpdateDatetime))
        if err != nil {
          pillarsLog.PillarsLogger.Print(err.Error())
          return nil, err
        }
      }
      return &commodity, err

7.2 Mongodb

   

Copy codeThe code is as follows:
err :=  mongoUtility.PictureCollection.Find(bson.M{“picturecode”:*pictureCode}).One(&picture)

Only the simplest example is given here. See MgO’s development documents for details. It’s still relatively simple.
8. Unit test considerations

    Test command go test – V (no more parameters)!) If there is no – V, only the results will be displayed and the debugging process will not be displayed. It is mainly used for debugging and development
    File format XXX_ Test. Go, but suggest to change to XXX_ You can change Test0. Go to something else if you like.
        Due to the principle of testing first, one or two functions can be tested at a time during development.
        This is equivalent to commenting out other tests
    When testing, the configuration file should be placed under the test directory. Don’t forget.
    Mentality, too many mistakes, one by one to have a good mentality.

9.LOG

Pay attention to the log in debugging.

If you don’t know where the API comes from, you can search doc directly.

   

Copy codeThe code is as follows:
package utility
    import “log”
    import “os”
    import “fmt”
    // Logger Model min variable.
    var Logger *log.Logger
    var outFile *os.File
    // init function if Logger if not inited will invoke this function
    func init() {
      if Logger == nil {
        propertyMap := ReadProperty(“pic.properties”)
        logFileName := propertyMap[“LogFile”]
        fmt.Println(“Initial and Open log file “, logFileName)
        var err error
        outFile, err = os.OpenFile(logFileName, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
        if err != nil {
          panic(err.Error())
        }
        Logger = log.New(outFile, “”, log.Ldate|log.Ltime|log.Llongfile)
      }
    }
    // CloseLogFile function : close Logger invoke file.
    func CloseLogFile() {
      outFile.Close()
    }

usage method:

   

Copy codeThe code is as follows:
utility.Logger.Println(“Log test”)

Recommended Today

Supervisor

Supervisor [note] Supervisor – H view supervisor command help Supervisorctl – H view supervisorctl command help Supervisorctl help view the action command of supervisorctl Supervisorctl help any action to view the use of this action 1. Introduction Supervisor is a process control system. Generally speaking, it can monitor your process. If the process exits abnormally, […]