WEB服務(wù)
啟動一個WEB服務(wù),Add添加寞忿、Find列表烛愧,Del刪除
go run main.go 服務(wù)可以正常運(yùn)行遍膜,添加,列表,查看也都是正常的
http://127.0.0.1:1234/goods/add
http://127.0.0.1:1234/goods/find
- main.go
package main
import (
"fmt"
"net/http"
_ "net/http/pprof" // 啟用pprof
"os"
"pf/goods"
)
var port string = "0.0.0.0:1234"
func main() {
os.Setenv("name", "pprof")
fmt.Println("listen", port)
http.HandleFunc("/goods/add", goods.Add)
http.HandleFunc("/goods/find", goods.Find)
http.HandleFunc("/goods/del", goods.Del)
err := http.ListenAndServe(port, nil)
if err != nil {
fmt.Println("http error:", err)
}
}
- goods.go
package goods
import (
"fmt"
"net/http"
"os"
"strconv"
)
type GoodsModel struct {
Id int
Name string
}
var Goods []*GoodsModel = make([]*GoodsModel, 0, 10)
var id int = 1
func Add(res http.ResponseWriter, req *http.Request) {
g := GoodsModel{
Id: id,
Name: os.Getenv("name") + "-" + strconv.Itoa(id),
}
Goods = append(Goods, &g)
fmt.Println("add ok", id, &g)
id++
res.Write([]byte("add ok"))
}
func Find(res http.ResponseWriter, req *http.Request) {
count := "count:" + strconv.Itoa(len(Goods)) + "\n"
c := "cap:" + strconv.Itoa(cap(Goods)) + "\n"
res.Write([]byte(count))
res.Write([]byte(c))
for k, g := range Goods {
str := fmt.Sprintf("k:%d, id:%d, name:%s\n", k, g.Id, g.Name)
res.Write([]byte(str))
}
}
func Del(res http.ResponseWriter, req *http.Request) {
Goods = make([]*GoodsModel, 0)
id = 1
res.Write([]byte("del ok"))
}
- 增加
http://127.0.0.1:1234/goods/add
- 列表
http://127.0.0.1:1234/goods/find
上面代碼測試看起貌似是正常的途样,如果訪問量大的時候會發(fā)現(xiàn)在,列表?xiàng)l數(shù)小于添加數(shù)
100請求成功濒憋,go未報錯
查看列表何暇,97條記錄,請求都成功了凛驮,go后臺沒有報錯裆站,為什么少了3條?(每次條數(shù)可能不一樣)
http://127.0.0.1:1234/goods/find
go 啟動增加參數(shù) race黔夭,檢測數(shù)據(jù)競爭
go run -race main.go
在重新執(zhí)行一下上面的測試
-
執(zhí)行
解決思路
1.加鎖宏胯,全局變局多個協(xié)程添加修改時,為全局變量加鎖
2.channel本姥,如果不需要實(shí)時寫入肩袍,可以先寫入channel,異步更新
3....
加鎖婚惫,請求1000次
查看結(jié)果氛赐,go未報錯,列表添加1000個成功