blog
blog copied to clipboard
Go语言动手写Web框架 - Gee第六天 错误恢复(Panic Recover) | 极客兔兔
https://geektutu.com/post/gee-day7.html
7天用 Go语言 从零实现Web框架教程(7 days implement golang web framework from scratch tutorial),用 Go语言/golang 动手写Web框架,从零实现一个Web框架,以 Gin 为原型从零设计一个Web框架。本文介绍了如何为Web框架增加错误处理机制。
r := gee.Default() 是怎么回事
r := gee.Default() 是怎么回事
gee.go#L40 默认实例使用 Logger
和 Recovery
中间件。
// gee.go
// Default use Logger() & Recovery middlewares
func Default() *Engine {
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
这是什么问题 2020/04/14 22:21:07 Router GET - / 2020/04/14 22:21:07 Router GET - /panic 2020/04/14 22:21:14 http: panic serving [::1]:7184: runtime error: index out of range [100] with length 1 goroutine 8 [running]: net/http.(*conn).serve.func1(0xc00005b220) c:/go/src/net/http/server.go:1767 +0x140 panic(0x7cd780, 0xc0000e6020) c:/go/src/runtime/panic.go:679 +0x1c0 main.main.func2(0xc0000f6000) E:/Github/go-web/main.go:101 +0x1d gee.(*Context).Next(0xc0000f6000) E:/Github/go-web/gee/context.go:47 +0x45 gee.(*router).handle(0xc000034be0, 0xc0000f6000) E:/Github/go-web/gee/router.go:92 +0x153 gee.(*Engine).ServeHTTP(0xc00003e340, 0x884d80, 0xc0000f2000, 0xc0000dc100) E:/Github/go-web/gee/gee.go:140 +0x310 net/http.serverHandler.ServeHTTP(0xc0000c6000, 0x884d80, 0xc0000f2000, 0xc0000dc100) c:/go/src/net/http/server.go:2802 +0xab net/http.(*conn).serve(0xc00005b220, 0x885380, 0xc0000de000) c:/go/src/net/http/server.go:1890 +0x87c created by net/http.(*Server).Serve c:/go/src/net/http/server.go:2927 +0x395 exit status 2
代码一样,模版那一章css引入也失败了,template模版怎么解析go的切片变量
在添加Recovery
中间件之前,通过访问越界下标的数组产生panic,但是web服务本身没有被down掉(崩溃),还可以继续处理正常的请求。所以有个疑问:panic是否会造成web服务的崩溃?
go版本:go1.13.5
@ayuayue 这个错误是故意设计的,下标越界触发panic。
@armstrong-liu net/http 的源码中,也使用了 recovery ,所以一般不会导致web服务崩溃,即其他请求不受影响。所以 Recovery 中间件在这里的作用还是保证所有请求都能正常响应,否则,panic 之后,就没回应了。之前没考虑到 net/http
内部实现这一点,文章内容有歧义,感谢你指出问题。
@geektutu @ayuayue 这个错误是故意设计的,下标越界触发panic。
触发了panic,其他路由可以正常返回,但是触发panic没有返回json,正常吗
收益匪浅, 感谢博主
@SourceLink 很高兴对你有帮助~
收获很多,对golang语言和gin框架熟悉程度加深,感谢博主😘😘😘
感谢楼主的无私奉献
跟着实现了一遍,还是有一点点成就感的。感谢tutu的精心分享!
recorve 为什么一定要有 c.Next()? 没有就会报panic
@wings-xue recorve 为什么一定要有 c.Next()? 没有就会报panic
因为defer recover机制只能针对于当前函数以及直接调用的函数可能参数的panic,所以在Recovery里面的c.Next()会执行下面这个handler
func(c *gee.Context) {
names := []string{"geektutu"}
c.String(http.StatusOK, names[100])
}
从而捕获到panic并恢复 如果没有c.Next(),则handler不是Recovery直接调用的函数,无法recover,panic被net/http自带的recover机制捕获
求讲跨域中间件,我是这样写的,但是失败了:
=========================cors.go====================================
import "fmt"
func CORSMiddleware() HandlerFunc {
return func(c *Context) {
fmt.Print("1")
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
fmt.Print("2")
if c.Req.Method == "OPTIONS" {
c.Fail(204,"cors err")
fmt.Print("err3")
return
}
c.Next()
}
}
============================main.go==================================
r.Use(Gouwa.CORSMiddleware())
recovery中间键是不是注册在logger中间键前面会好一些
看完了gee-web,十分收益,感谢博主!
谢谢
完结撒兔兔,谢谢大佬
/panic 并不会宕机啊。。只是这个handler报错 其他handler 正常运行啊 为啥..
官方推荐使用CallersFrames
来获取调用栈信息
func trace(message string) string {
var pcs [32]uintptr
n := runtime.Callers(3, pcs[:])
var str strings.Builder
str.WriteString(message + "\nTraceback:")
frames := runtime.CallersFrames(pcs[:n])
for {
frame, more := frames.Next()
str.WriteString(fmt.Sprintf("\n\t%s:%d", frame.File, frame.Line))
if !more {
break
}
}
return str.String()
}
文中main函数启动的时候,忘了写用Use把Recovery中间件注册进去了
@Alex-Jee 文中main函数启动的时候,忘了写用Use把Recovery中间件注册进去了
Default里面写了
参考博主的教程撸了一个练手项目github.com/junbin-yang/see,经过不断优化性能也优于gin。学到了不少东西。感谢感谢。
感谢
谢谢@geektutu,有兴趣深入学习的小伙伴可以了解一下gin-vue-admin这个项目,绝对过瘾。
参考博主的教程撸了一个练手项目github.com/junbin-yang/see,经过不断优化性能也优于gin。学到了不少东西。感谢感谢。
为什么你们的练手项目都能如此优秀
受益匪浅,感谢博主。
感谢感谢感谢,感觉自己对GOLANG网络开发相关的理解比之前强多了555