基於Go的web開發示例

1、簡單web服務

  1. Go語言內置了Web服務;net/http 標準庫中包含有關HTTP協議的所有功能。
  2. 註冊請求處理函數 func ( w http.ResponseWriter , r *http.Request)
  3. 該函數接收兩個參數:一個http.ResponseWriter 用於text/html響應。http.Request 其中包含有關此HTTP請求的所有信息,包括URL或者請求頭字段之類的信息。
  4. 偵聽http連接 http.ListenAndServe(":80",nil)
  5. 代碼
package main
 
import (
    "fmt"
    "net/http"
)
 
func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "你好,你的請求是 %s\n", r.URL.Path)
    })
 
    http.ListenAndServe(":80", nil)
}


2、Web開發框架-Gin

Gin 是一個 go 寫的 web 框架,具有高性能的優點。官方地址:https://github.com/gin-gonic/gin

  1. 下載並安裝

    a: 如果比較慢,設置代理: https://goproxy.io/zh/docs/introduction.html

    go env -w GO111MODULE=on
    go env -w GOPROXY=https://goproxy.io,direct
    
    
    

    b:go get -u github.com/gin-gonic/gin

2.cannot find module providing package github.com/gin-gonic/gin: working directory is not part of a module

將代碼放在 $GOPATH\src 目錄下,執行:

go mod init

go mod vendor

go build  web.go

3.示例

package main
 
import (
 
	"net/http"
	"strconv"
	"time"
	"github.com/gin-gonic/gin"
)
 
type User struct {
	ID          int64
	Name        string
	Age         int
	CreatedTime time.Time
	UpdatedTime time.Time
	IsDeleted   bool
}
 
func main() {
    //初始化引擎
	r := gin.Default()
 
    //簡單的Get請求
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
 
    //GET請求通過name獲取參數  /user/test
	r.GET("/user/:name", func(c *gin.Context) {
		name := c.Param("name")
		c.String(http.StatusOK, "Hello %s", name)
	})
 
    //GET請求通過正常的URL獲取參數  /getuser?id=2
	r.GET("/getuser", func(c *gin.Context) {
		rid := c.DefaultQuery("id", "1")
		id, _ := strconv.ParseInt(rid, 10, 64)
		user := User{ID: id, Age: 32, CreatedTime: time.Now(), UpdatedTime: time.Now(), IsDeleted: true}
		c.JSON(http.StatusOK, user)
	})
 
    //POST請求通過綁定獲取對象
	r.POST("/adduser", func(c *gin.Context) {
		var user User
		err := c.ShouldBind(&user)
		if err == nil {
			c.JSON(http.StatusOK, user)
		} else {
			c.String(http.StatusBadRequest, "請求參數錯誤", err)
		}
	})
 
	  //post 請求  json 格式話    http://localhost:8080/json
	  r.GET("/json",func (c *gin.Context)  {
		c.JSON(http.StatusOK,gin.H{"name":"post 請求  json 格式話","age":18})
	  })

	  //delete 請求 xml 格式化   http://localhost:8080/xml
	  r.GET("/xml",func (c *gin.Context)  {
		c.XML(http.StatusOK,gin.H{"name":"delete 請求 xml 格式化","age":18})
	  })

	  //patch 請求  yaml 格式化   http://localhost:8080/yaml
	  r.GET("/yaml",func (c *gin.Context)  {
		c.YAML(http.StatusOK,gin.H{"name":"patch 請求 yaml 格式化","age":18})
	  })

	  //get請求 html界面顯示   http://localhost:8080/html
	  r.GET("/html",func (c *gin.Context)  {
		r.LoadHTMLGlob("item/*")  //這是前臺的index
		c.HTML(http.StatusOK,"index.html",nil)
	  })
  
  	  //跳轉到上傳頁面
	  r.GET("/preupload",func (c *gin.Context)  {
		r.LoadHTMLGlob("item/*")  //這加載的頁面目錄
		c.HTML(http.StatusOK,"upload.html",nil)
	  })
  
	// 當訪問地址爲/upload時執行後面的函數
    r.POST("/upload", func(c *gin.Context) {
        //獲取表單數據 參數爲name值
        f, err := c.FormFile("f1")
        //錯誤處理
        if err != nil {
            c.JSON(http.StatusBadRequest, gin.H{
                "error": err,
            })
            return
        } else {
            //將文件保存至本項目根目錄中
            c.SaveUploadedFile(f, f.Filename)
            //保存成功返回正確的Json數據
            c.JSON(http.StatusOK, gin.H{
                "message": "OK",
            })
        }

    })
  
	r.Run(":9002") // listen and serve on 0.0.0.0:9002
}

在web.go的當前目前下創建item 文件夾,並創建upload.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>上傳文件示例</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="f1">
    <input type="submit" value="上傳">
</form>
</body>
</html>

3 . websocket 開發

package main
 
import (
    "fmt"
    "github.com/gorilla/websocket"
    "net/http"
)
 
var (

    upgrader = websocket.Upgrader{
	//允許跨域訪問
        CheckOrigin:func(r *http.Request) bool{
            return true
        },
    }
)
 
 
 
func wsHandler(w http.ResponseWriter,r *http.Request)  {
 
    var (
        conn *websocket.Conn
        err error
        data []byte
    )
	 //Upgrade websocket(返回給客戶端的消息)
    if conn,err = upgrader.Upgrade(w,r,nil);err != nil{
        return
    }
 
    for{
        if _,data,err = conn.ReadMessage();err != nil{
            goto ERR
        }
		//打印數據輸出
        fmt.Println(data)
        if err = conn.WriteMessage(websocket.TextMessage,[]byte("服務器數據"));err !=nil{
            goto ERR
        }
    }
    ERR:
        conn.Close()
 
}
 
func main() {
    http.HandleFunc("/ws",wsHandler)
    http.ListenAndServe("0.0.0.0:8888",nil)
}

websocket地址:ws://localhost:8888/ws

測試頁面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script>
        window.addEventListener("load", function(evt) {
            var output = document.getElementById("output");
            var input = document.getElementById("input");
            var ws;
            var print = function(message) {
                var d = document.createElement("div");
                d.innerHTML = message;
                output.appendChild(d);
            };
            document.getElementById("open").onclick = function(evt) {
                if (ws) {
                    return false;
                }
                ws = new WebSocket("ws://localhost:8888/ws");
                ws.onopen = function(evt) {
                    print("OPEN");
                }
                ws.onclose = function(evt) {
                    print("CLOSE");
                    ws = null;
                }
                ws.onmessage = function(evt) {
                    print("RESPONSE: " + evt.data);
                }
                ws.onerror = function(evt) {
                    print("ERROR: " + evt.data);
                }
                return false;
            };
            document.getElementById("send").onclick = function(evt) {
                if (!ws) {
                    return false;
                }
                print("SEND: " + input.value);
                ws.send(input.value);
                return false;
            };
            document.getElementById("close").onclick = function(evt) {
                if (!ws) {
                    return false;
                }
                ws.close();
                return false;
            };
        });
    </script>
</head>
<body>
<table>
    <tr><td valign="top" width="50%">
            <p>Click "Open" to create a connection to the server,
                "Send" to send a message to the server and "Close" to close the connection.
                You can change the message and send multiple times.
            </p>
            <form>
                <button id="open">Open</button>
                <button id="close">Close</button>
                <input id="input" type="text" value="Hello world!">
                <button id="send">Send</button>
            </form>
        </td><td valign="top" width="50%">
            <div id="output"></div>
        </td></tr></table>
</body>
</html>

4. 數據庫增刪改查操作

a. 下載mysql驅動

''

package main

import (
    "bytes"
	"database/sql"
	"fmt"
	"net/http"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
)

func main(){
	//數據庫連接池db
    //"用戶名:密碼@[連接方式](主機名:端口號)/數據庫名"
    db, err :=sql.Open("mysql","root:root@123ab@(127.0.0.1:3306)/testdatabases") // 設置連接數據庫的參數
 
   if err != nil {
		fmt.Print(err.Error())
	}
	defer db.Close()
	
	db.SetMaxIdleConns(20)
	
	db.SetMaxOpenConns(20)
	// make sure connection is available
	err = db.Ping()
	if err != nil {
		fmt.Print(err.Error())
	}
	
	fmt.Print("數據庫連接正常")
	type Person struct {
		Id         int
		First_Name string
		Last_Name  string
	}
	router := gin.Default()
	//根據ID查詢用戶信息
	router.GET("/person/:id", func(c *gin.Context) {
		var (
			person Person
			result gin.H
		)
		id := c.Param("id")
		row := db.QueryRow("select id, first_name, last_name from person where id = ?;", id)
		err = row.Scan(&person.Id, &person.First_Name, &person.Last_Name)
		if err != nil {
			// If no results send null
			result = gin.H{
				"result": nil,
				"count":  0,
			}
		} else {
			result = gin.H{
				"result": person,
				"count":  1,
			}
		}
		c.JSON(http.StatusOK, result)
	})
	// 獲取所有用戶
	router.GET("/persons", func(c *gin.Context) {
		var (
			person  Person
			persons []Person
		)
		rows, err := db.Query("select id, first_name, last_name from person;")
		if err != nil {
			fmt.Print(err.Error())
		}
		for rows.Next() {
			err = rows.Scan(&person.Id, &person.First_Name, &person.Last_Name)
			persons = append(persons, person)
			if err != nil {
				fmt.Print(err.Error())
			}
		}
		defer rows.Close()
		c.JSON(http.StatusOK, gin.H{
			"result": persons,
			"count":  len(persons),
		})
	})
	// 新增用戶
	router.POST("/person", func(c *gin.Context) {
		var buffer bytes.Buffer
		first_name := c.PostForm("first_name")
		last_name := c.PostForm("last_name")
		stmt, err := db.Prepare("insert into person (first_name, last_name) values(?,?);")
		if err != nil {
			fmt.Print(err.Error())
		}
		_, err = stmt.Exec(first_name, last_name)
		if err != nil {
			fmt.Print(err.Error())
		}
		// Fastest way to append strings
		buffer.WriteString(first_name)
		buffer.WriteString(" ")
		buffer.WriteString(last_name)
		defer stmt.Close()
		name := buffer.String()
		c.JSON(http.StatusOK, gin.H{
			"message": fmt.Sprintf(" %s successfully created", name),
		})
	})
	// PUT - 更新用戶信息
	router.PUT("/person", func(c *gin.Context) {
		var buffer bytes.Buffer
		id := c.Query("id")
		first_name := c.PostForm("first_name")
		last_name := c.PostForm("last_name")
		stmt, err := db.Prepare("update person set first_name= ?, last_name= ? where id= ?;")
		if err != nil {
			fmt.Print(err.Error())
		}
		_, err = stmt.Exec(first_name, last_name, id)
		if err != nil {
			fmt.Print(err.Error())
		}
		// Fastest way to append strings
		buffer.WriteString(first_name)
		buffer.WriteString(" ")
		buffer.WriteString(last_name)
		defer stmt.Close()
		name := buffer.String()
		c.JSON(http.StatusOK, gin.H{
			"message": fmt.Sprintf("Successfully updated to %s", name),
		})
	})
	//根據ID刪除用戶
	router.DELETE("/person", func(c *gin.Context) {
		id := c.Query("id")
		stmt, err := db.Prepare("delete from person where id= ?;")
		if err != nil {
			fmt.Print(err.Error())
		}
		_, err = stmt.Exec(id)
		if err != nil {
			fmt.Print(err.Error())
		}
		c.JSON(http.StatusOK, gin.H{
			"message": fmt.Sprintf("Successfully deleted user: %s", id),
		})
	})
	router.Run(":3000")
}
 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章