blog
blog copied to clipboard
Go语言动手写Web框架 - Gee第一天 http.Handler | 极客兔兔
https://geektutu.com/post/gee-day1.html
7天用 Go语言 从零实现Web框架教程(7 days implement golang web framework from scratch tutorial),用 Go语言/golang 动手写Web框架,从零实现一个Web框架,从零设计一个Web框架。本文介绍了Go标准库 net/http 和 http.Handler 接口的使用,拦截所有的 HTTP 请求,交给Gee框架处理。
谢谢站主提供的项目经验,我有个问题不是很懂,网上查了资料也没有找到,http.ListenAndServe(":9999", engine)第二个参数是一个interface类型,里面有有一个ServeHTTP()方法,您代码中传入了一个结构体里面有一个ServeHTTP()方法,但是并没有调用啊,怎么就执行了。结构体不是应该先赋值给接口,接口才能够调用结构体中的方法吗。在下才疏学浅,想了2天,查了百度,还是觉得迷迷糊糊的,希望大神能够赐教,感激不尽
@MasterCl 第二个参数类型是接口类型 http.Handler ,Handler 的定义博文中已经贴了,是从 http 的源码中找到的。
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}
func ListenAndServe(address string, h Handler) error
在 Go 语言中,实现了接口方法的 struct 都可以强制转换为接口类型。你可以这么写:
handler := (http.Handler)(engine) // 手动转换为借口类型
log.Fatal(http.ListenAndServe(":9999", handler))
然后,ListenAndServe 方法里面会去调用 handler.ServeHTTP() 方法,你感兴趣,可以在 http 的源码中找到调用的地方。但是这么写是多余的,传参时,会自动进行参数转换的。所以直接传入engine 即可。
@geektutu 非常感谢,我理解了
第一天get,学框架的同时学习go。主要学习到:1. struct添加method 2. go mod 使用
博主文章写得真好,默默学习膜拜一波
博主写的真的是太赞了👍
建议博主把
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
key := req.Method + "-" + req.URL.Path
if handler, ok := engine.router[key]; ok {
handler(w, req)
} else {
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
}
修改为
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
key := req.Method + "-" + req.URL.Path
if handler, ok := engine.router[key]; ok {
handler(w, req)
} else {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
}
跪谢大佬的教程,在google搜索出来的web实例教程大多都是用标准库写一个简易web应用,想进阶却难以突破,直到看见大佬这份框架教程。
@maogou 非常感谢你的建议,下次更新的时候我改一下,这里确实是忘记设置返回码了,不标准。
@tumaowolf 感谢你的认可,web 是第一期,后面还有三期~
太强了,谢谢,财大牛皮😃
@fangbaogang 感谢认可~ 😁
正想学学http 相关知识, 看了第一天就感觉很好. 感谢tutu. 赞赏支持了下.
@wzy2687 感谢你的支持和赞赏 😸,希望能对你有用~
大佬牛批,看你的文章真的通俗易懂,能让小白看懂的文章真的赞,跟读go语言高级编程第一章一样的感觉,爽,谢谢tutu
@chocolateszz 感谢你的认可,通俗易懂是这个系列的终极目的~
@CaocaoWym 谢谢站主提供的项目经验,我有个问题不是很懂,网上查了资料也没有找到,http.ListenAndServe(":9999", engine)第二个参数是一个interface类型,里面有有一个ServeHTTP()方法,您代码中传入了一个结构体里面有一个ServeHTTP()方法,但是并没有调用啊,怎么就执行了。结构体不是应该先赋值给接口,接口才能够调用结构体中的方法吗。在下才疏学浅,想了2天,查了百度,还是觉得迷迷糊糊的,希望大神能够赐教,感激不尽
这个是标准库里的逻辑吧,第二个参数传nil的话,标准库里默认用DefaultServeMux这个接口,传了你自定义的,标准库就调用你自定义的。if xx == nil 判断下就知道了。 我看了下源码
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}
mark 跟进学习
@mesiyar 希望有所收获,ღ( ´・ᴗ・` )比心
谢谢站主。最近打算学go,看了tour of go之后就过来跟你的教程啦
@AcVoyager 嗯,加油,希望对你有帮助~
@CaocaoWym 谢谢站主提供的项目经验,我有个问题不是很懂,网上查了资料也没有找到,http.ListenAndServe(":9999", engine)第二个参数是一个interface类型,里面有有一个ServeHTTP()方法,您代码中传入了一个结构体里面有一个ServeHTTP()方法,但是并没有调用啊,怎么就执行了。结构体不是应该先赋值给接口,接口才能够调用结构体中的方法吗。在下才疏学浅,想了2天,查了百度,还是觉得迷迷糊糊的,希望大神能够赐教,感激不尽
因为这个结构体有个方法已经实现了SeverHTTP,也就是说engine实现了Handler接口,故可以直接调用了
谢谢大佬这一系列!
@geektutu @MasterCl 第二个参数类型是接口类型
http.Handler,Handler的定义博文中已经贴了,是从http的源码中找到的。type Handler interface { ServeHTTP(w ResponseWriter, r *Request) } func ListenAndServe(address string, h Handler) error在 Go 语言中,实现了接口方法的 struct 都可以强制转换为接口类型。你可以这么写:
handler := (http.Handler)(engine) // 手动转换为借口类型 log.Fatal(http.ListenAndServe(":9999", handler))然后,
ListenAndServe方法里面会去调用handler.ServeHTTP()方法,你感兴趣,可以在 http 的源码中找到调用的地方。但是这么写是多余的,传参时,会自动进行参数转换的。所以直接传入engine 即可。
是否可以理解为:自己重写了ServeHTTP方法,所以默认会自动调用重写后的ServeHTTP
这一章跳下一章的链接对不上
我测试的时候发现第一个 example 不会报 404,这和第二个 example 不一样。 查了下文档,原来默认使用的 ServerMux 有特殊的模式匹配规则。
我是一只运维,对go初学很有帮助。感谢兔兔。
也就是说,只要传入任何实现了 ServerHTTP 【接口】的实例。这里【接口】应该改成方法吧。
@nm2006717 也就是说,只要传入任何实现了 ServerHTTP 【接口】的实例。这里【接口】应该改成方法吧。 接口 = &类型 (该类型实现了接口中的所有方法),接口和具体方法的实现是这样传递的,方法由调用者去保证,ServeHttp定义的就是 type Handler interface { ServeHTTP(ResponseWriter, *Request) } 接口本来就是一个函数指针类型的集合
如果有学过springmvc的同学,可以发现这里的engine就是就是dispatchservlet
请问,还是需要引入gee框架吗?谢谢
go.mod我这样写还是找不到依赖,麻烦问一下各位大佬知道这个怎么做吗