go web学习(五)
跟着刘旭老师学go web做的笔记
【Go Web 编程快速入门【Golang/Go语言】(完结)】 https://www.bilibili.com/video/BV1Xv411k7Xn/?p=27&share_source=copy_web&vd_source=03c1dc52eeb3747825ecad0412c18ab1
https
【HTTP/1.1,HTTP/2和HTTP/3的区别】 https://www.bilibili.com/video/BV1vv4y1U77y/?share_source=copy_web&vd_source=03c1dc52eeb3747825ecad0412c18ab1
http 明文传输 中间人也能看见
https TLS传输层安全 加密数据,只有客户端和服务器知道它们在说啥
http Listener
http.ListenAndServe 函数
http.ListenAndServeTLS 函数
在Terminal里输入
go run E:\GO\src\crypto\tls\generate_cert.go -h
go run E:\GO\src\crypto\tls\generate_cert.go -host localhost
//就是你自己的储存目录下面的\src\crypto\tls\generate_cert.go
//设置加密证书
//出现 cert.pem 和key.pem文件
http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello"))
})
http.ListenAndServeTLS(":8080","cert.pem","key.pem",nil)
//现在是https://localhost:8080/了
HTTP/2
客户端与服务器沟通
HTTP/1.1 请求和响应
HTTP/2 Stream (每个数据类型都可以单独优化)
- 请求多路复用
- Header 压缩
- 默认安全
-
- HTTP ,但很多决定不支持 HTTP
-
- HTTPS
- Server Push
Server Push
http.HandleFunc("/home",func(w http.ResponseWriter, r *http.Request) {
if pusher,ok := w.(http.Pusher);ok{
//Push的第一个目标是我们要推送的文件,第二个是一些选项
pusher.Push("/css/app.css",&http.PushOptions{
Header: http.Header{"Content-Type": []string{"text/css"}},
})
}
t,_ := template.ParseFiles("home.html")
t.ExecuteTemplate(w,"home.html",nil)
})
http.ListenAndServeTLS(":8080","cert.pem","key.pem",nil)
测试
import "testing"
测试 Model 层
-
user_test.go
测试代码所在文件的名称以 _test 结尾
对于生产编译,不会包含以 _test 结尾的文件
对于测试编译,会包含以 _test 结尾的文件 -
func TestUpdatesModifiedTime(t *testing.T) { … }
测试函数名应以 Test 开头(需要导出)
函数名需要表达出被验证的特性
测试函数的参数类型是 *testing.T,它会提供测试相关的一些工具
目前文件结构是goWeb-blog包,底下有mian.go,有moddel文件夹,
model文件夹下有两个文件,company.go和测试文件company_test.go
model/company.go
//company.go
package model
import "strings"
type Company struct {
ID int
Name string
Country string
}
func (c *Company) GetCompanyType() (result string) {
if strings.HasSuffix(c.Name, ".LTD"){
result = "Limited Liability Company"
}else{
result = "Others"
}
return
}
model/company_test.go
//company_test.go
package model
import (
"fmt"
"testing"
)
func TestGetCompanyType(t *testing.T) {
var c = &Company{
ID: 123,
Name: "ABC.LTD",
Country: "China",
}
var x = c.GetCompanyType()
if x != "Limited Liability Company"{
fmt.Println("the type is other")
}else{
fmt.Println("get Limited Liability Company")
}
}
执行命令行
go test goWeb-blog/model
//注意,假如你这个测试文件和main.go同级,就可以直接
// go test
//否则就得加路径
得到结果
ok goWeb-blog/model 0.501s
测试 Controller 层
- 为了尽量保证单元测试的隔离性,测试不要使用例如数据库、外部API、文件系统等外部资源。
- 模拟请求和响应
- 需要使用
"net/http/httptest"
提供的功能
NewRequest 函数 r
- func NewRequest(method, url string, body io.Reader) (*Request, error)
-
- method:HTTP Method
-
- url:请求的 URL
-
- body:请求的 Body
-
- 返回的 *Request 可以传递给 handler 函数
ResponseRecorder 响应记录器 w
type ResponseRecorder {
Code int // 状态码 200、500…
HeaderMap http.Header // 响应的 header
Body *bytes.Buffer // 响应的 body
Flushed bool // 缓存是否被 flush 了
}
用来捕获从 handler 返回的响应,只是做记录
可以用于测试断言
注:上个测试的model这次还会用到
普通文件controller/company.go
// controller/company.go
package controller
import (
"encoding/json"
"net/http"
"timer/goWeb-sql/model"
)
func RegisterRoutes() {
http.HandleFunc("/company", handlerCompany)
}
func handlerCompany(w http.ResponseWriter, r *http.Request){
c:= model.Company{
ID: 123,
Name: "google",
Country: "USA",
}
//进行json编码并写到响应里面
enc := json.NewEncoder(w)
enc.Encode(c)
}
测试文件 controller/company_test.go
// controller/company_test.go
package controller
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"timer/goWeb-sql/model"
)
func TestHandlerCompanyCorrect(t *testing.T) {
r:=httptest.NewRequest(http.MethodGet,"/companier",nil)
w:=httptest.NewRecorder()
handlerCompany(w,r)
result,_:= ioutil.ReadAll(w.Result().Body)
c:= model.Company{}
json.Unmarshal(result, &c)
if c.ID != 123{
t.Errorf("failed to handle company correctly")
}
}
命令行
这个路径啊,就看在这个包的引用路径,比如我测试文件引用本包的model,
"timer/goWeb-sql/model",那就把model抠了,换成controller就行
(当时起名字好像就是叫的time/goWeb-sql,稍微有点歧义)
go test timer/goWeb-sql/controller
结果
//假如成功
ok timer/goWeb-sql/controller 0.687s
//假如失败
--- FAIL: TestHandlerCompanyCorrect (0.00s)
company_test.go:20: failed to handle company correctly
FAIL
FAIL timer/goWeb-sql/controller 0.723s
FAIL
Profiling性能分析
能分析什么
- 内存消耗
- CPU 使用
- 阻塞的 goroutine
- 执行追踪
- 还有一个 Web 界面:应用的实时数据
等等,可以监听的种类在增多
如何进行分析
import _ "net/http/pprof"
设置一些监听的 URL,它们会提供各类诊断信息
go tool pprof http://localhost:8000/debug/pprof/heap // 内存
从应用获取内存 dump:应用在使用哪些内存,它们会去哪
go tool pprof http://localhost:8000/debug/pprof/profile // CPU
CPU 的快照,可以看到谁在用 CPU
go tool pprof http://localhost:8000/debug/pprof/block // goroutine
看到阻塞的 goroutine
go tool pprof http://localhost:8000/debug/pprof/trace?seconds=5 // trace
监控这段时间内,什么在执行,什么在调用什么…
http://localhost:8000/debug/pprof // 网页
一个快照,刷新页面时的诊断数据
main函数
package main
import (
"fmt"
"timer/goWeb-sql/controller"
"net/http"
_ "net/http/pprof"
)
func main(){
server:= http.Server{
Addr: "localhost:8080",
}
controller.RegisterRoutes()
fmt.Println("Server starting now...")
//goroutine 没有中间件,这样性能分析工具就不会受到中间件影响
go http.ListenAndServe("localhost:8000",nil)
//自己的频道,可以添加中间件
server.ListenAndServe()
}
命令行
go run .
网页:
- 打开
http://localhost:8080/company
- 再打开
http://localhost:8000/debug/pprof/
(东西挺多的可以看看)
打开一个新的命令行界面(原来那个不要关)
go tool pprof http://localhost:8000/debug/pprof/heap
然后可以进行交互
比如: help -> top -> png
若是png无法执行要求下载,那就下吧 graphviz.org/download/
下好了以后,继续png
就能生成内存分析的图片
实例
这个是我做的,臃肿的有bug的博客项目。。。。。。
session有点问题。。。。。。哦我实力好弱
需要参考可以看看
https://gitee.com/time-wuling/simpleBlog