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")
}