blog icon indicating copy to clipboard operation
blog copied to clipboard

Go语言动手写Web框架 - Gee第六天 错误恢复(Panic Recover) | 极客兔兔

Open geektutu opened this issue 4 years ago • 54 comments

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框架增加错误处理机制。

geektutu avatar Jan 08 '20 17:01 geektutu

r := gee.Default() 是怎么回事

yywwann avatar Mar 05 '20 08:03 yywwann

r := gee.Default() 是怎么回事

gee.go#L40 默认实例使用 LoggerRecovery 中间件。

// gee.go
// Default use Logger() & Recovery middlewares
func Default() *Engine {
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

geektutu avatar Mar 05 '20 09:03 geektutu

这是什么问题 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

ayuayue avatar Apr 14 '20 14:04 ayuayue

代码一样,模版那一章css引入也失败了,template模版怎么解析go的切片变量

ayuayue avatar Apr 14 '20 14:04 ayuayue

在添加Recovery中间件之前,通过访问越界下标的数组产生panic,但是web服务本身没有被down掉(崩溃),还可以继续处理正常的请求。所以有个疑问:panic是否会造成web服务的崩溃?

go版本:go1.13.5

armstrong-liu avatar Apr 16 '20 06:04 armstrong-liu

@ayuayue 这个错误是故意设计的,下标越界触发panic。

geektutu avatar Apr 16 '20 09:04 geektutu

@armstrong-liu net/http 的源码中,也使用了 recovery ,所以一般不会导致web服务崩溃,即其他请求不受影响。所以 Recovery 中间件在这里的作用还是保证所有请求都能正常响应,否则,panic 之后,就没回应了。之前没考虑到 net/http 内部实现这一点,文章内容有歧义,感谢你指出问题。

geektutu avatar Apr 16 '20 09:04 geektutu

@geektutu @ayuayue 这个错误是故意设计的,下标越界触发panic。

触发了panic,其他路由可以正常返回,但是触发panic没有返回json,正常吗

ayuayue avatar Apr 17 '20 00:04 ayuayue

收益匪浅, 感谢博主

SourceLink avatar Apr 20 '20 09:04 SourceLink

@SourceLink 很高兴对你有帮助~

geektutu avatar Apr 21 '20 01:04 geektutu

收获很多,对golang语言和gin框架熟悉程度加深,感谢博主😘😘😘

xx444812313 avatar Apr 21 '20 09:04 xx444812313

感谢楼主的无私奉献

woshihuo12 avatar Apr 26 '20 09:04 woshihuo12

跟着实现了一遍,还是有一点点成就感的。感谢tutu的精心分享!

ppd0705 avatar May 05 '20 03:05 ppd0705

recorve 为什么一定要有 c.Next()? 没有就会报panic

wings-xue avatar Mar 10 '21 08:03 wings-xue

@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机制捕获

zhcoders avatar Apr 09 '21 10:04 zhcoders

求讲跨域中间件,我是这样写的,但是失败了:

=========================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())

CAGeng avatar Apr 12 '21 13:04 CAGeng

recovery中间键是不是注册在logger中间键前面会好一些

puck1006 avatar Jun 30 '21 15:06 puck1006

看完了gee-web,十分收益,感谢博主!

JohnBing avatar Jul 16 '21 10:07 JohnBing

谢谢

Chadnon avatar Jul 17 '21 08:07 Chadnon

完结撒兔兔,谢谢大佬

callmePicacho avatar Aug 08 '21 11:08 callmePicacho

/panic 并不会宕机啊。。只是这个handler报错 其他handler 正常运行啊 为啥..

dashuaiduan avatar Sep 27 '21 07:09 dashuaiduan

官方推荐使用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()
}

joewongex avatar Oct 16 '21 06:10 joewongex

文中main函数启动的时候,忘了写用Use把Recovery中间件注册进去了

Alex-Jee avatar Oct 27 '21 09:10 Alex-Jee

@Alex-Jee 文中main函数启动的时候,忘了写用Use把Recovery中间件注册进去了

Default里面写了

fanandli avatar Dec 10 '21 02:12 fanandli

参考博主的教程撸了一个练手项目github.com/junbin-yang/see,经过不断优化性能也优于gin。学到了不少东西。感谢感谢。

junbin-yang avatar Dec 11 '21 12:12 junbin-yang

感谢

018429 avatar Dec 13 '21 08:12 018429

谢谢@geektutu,有兴趣深入学习的小伙伴可以了解一下gin-vue-admin这个项目,绝对过瘾。

DurantVivado avatar Dec 21 '21 07:12 DurantVivado

参考博主的教程撸了一个练手项目github.com/junbin-yang/see,经过不断优化性能也优于gin。学到了不少东西。感谢感谢。

为什么你们的练手项目都能如此优秀

fatFire avatar Feb 13 '22 08:02 fatFire

受益匪浅,感谢博主。

yyqingshui avatar May 06 '22 07:05 yyqingshui

感谢感谢感谢,感觉自己对GOLANG网络开发相关的理解比之前强多了555

luyi404 avatar May 15 '22 11:05 luyi404