1、簡單web服務
- Go語言內置了Web服務;net/http 標準庫中包含有關HTTP協議的所有功能。
- 註冊請求處理函數 func ( w http.ResponseWriter , r *http.Request)
- 該函數接收兩個參數:一個http.ResponseWriter 用於text/html響應。http.Request 其中包含有關此HTTP請求的所有信息,包括URL或者請求頭字段之類的信息。
- 偵聽http連接 http.ListenAndServe(":80",nil)
- 代碼
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
-
下載並安裝
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驅動
- go get -u github.com/go-sql-driver/mysql
- go get -u github.com/gin-gonic/gin
''
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")
}