Golang学习之net/http 包使用模式
译注: 这篇文章的内容非常基础,也非常容易理解。原文地址,感觉是最能清晰的讲述了net/http包的用法的一篇,故翻译一下共享之。 一切的基础:ServeMux 和 Handler Go 语言中处理 HTTP 请求主要跟两个东西相关: 处理器(Handler)负责输出HTTP响应的头和正文。任何满足了 ServeHTTP(http.ResponseWriter,*http.Request)
Go 语言的 HTTP 包自带了几个函数用作常用处理器,比如 $ mkdir handler-example
$ cd handler-example
$ touch main.go
//File: main.go
package main
import (
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
rh := http.RedirectHandler("http://example.org",307)
mux.Handle("/foo",rh)
log.Println("Listening...")
http.ListenAndServe(":3000",mux)
}
快速地过一下代码: 在 然后我们使用 接下来我们使用 最后我们创建了一个新的服务器,并通过 继续,运行一下这个程序: $ go run main.go
Listening...
然后在浏览器中访问 明察秋毫的你应该能注意到一些有意思的事情: 我们之所以能这么做,是因为 对我来说,将 自定义处理器(Custom Handlers) 让我们创建一个自定义的处理器,功能是将以特定格式输出当前的本地时间: type timeHandler struct {
format string
}
func (th *timeHandler) ServeHTTP(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(th.format)
w.Write([]byte("The time is: " + tm))
}
这个例子里代码本身并不是重点。 真正的重点是我们有一个对象(本例中就是个 我们把这个集成到具体的示例里: //File: main.go
package main
import (
"log"
"net/http"
"time"
)
type timeHandler struct {
format string
}
func (th *timeHandler) ServeHTTP(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(th.format)
w.Write([]byte("The time is: " + tm))
}
func main() {
mux := http.NewServeMux()
th := &timeHandler{format: time.RFC1123}
mux.Handle("/time",th)
log.Println("Listening...")
http.ListenAndServe(":3000",mux)
}
现在当我们运行这个应用, 访问一下这个地址看一下效果:http://localhost:3000/time 。 注意我们可以在多个路由中轻松的复用 func main() {
mux := http.NewServeMux()
th1123 := &timeHandler{format: time.RFC1123}
mux.Handle("/time/rfc1123",th1123)
th3339 := &timeHandler{format: time.RFC3339}
mux.Handle("/time/rfc3339",th3339)
log.Println("Listening...")
http.ListenAndServe(":3000",mux)
}
将函数作为处理器 对于简单的情况(比如上面的例子),定义个新的有 任何有 如果你听起来还有些困惑,可以尝试看一下[相关的源代码]http://golang.org/src/pkg/net…。你将会看到让一个函数对象满足 让我们使用这个技术重新实现一遍 //File: main.go
package main
import (
"log"
"net/http"
"time"
)
func timeHandler(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(time.RFC1123)
w.Write([]byte("The time is: " + tm))
}
func main() {
mux := http.NewServeMux()
// Convert the timeHandler function to a HandlerFunc type
th := http.HandlerFunc(timeHandler)
// And add it to the ServeMux
mux.Handle("/time",th)
log.Println("Listening...")
http.ListenAndServe(":3000",mux)
}
实际上,将一个函数转换成 我们使用便捷方式重写 func main() { mux := http.NewServeMux() mux.HandleFunc("/time",timeHandler) log.Println("Listening...") http.ListenAndServe(":3000",mux) }
绝大多数情况下这种用函数当处理器的方式工作的很好。但是当事情开始变得更复杂的时候,就会有些产生一些限制了。 你可能已经注意到了,跟之前的方式不同,我们不得不将时间格式硬编码到 一个优雅的方式是将我们处理器放到一个闭包中,将我们要使用的变量带进去: //File: main.go
package main
import (
"log"
"net/http"
"time"
)
func timeHandler(format string) http.Handler {
fn := func(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(format)
w.Write([]byte("The time is: " + tm))
}
return http.HandlerFunc(fn)
}
func main() {
mux := http.NewServeMux()
th := timeHandler(time.RFC1123)
mux.Handle("/time",mux)
}
首先是创建了一个 其次我们的闭包函数满足 在上面的例子中我们已经可以传递一个简单的字符串给处理器。但是在实际的应用中可以使用这种方法传递数据库连接、模板组,或者其他应用级的上下文。使用全局变量也是个不错的选择,还能得到额外的好处就是编写更优雅的自包含的处理器以便测试。 你也可能见过相同的写法,像这样: func timeHandler(format string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(format)
w.Write([]byte("The time is: " + tm))
})
}
或者在返回时,使用一个到 func timeHandler(format string) http.HandlerFunc {
return func(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(format)
w.Write([]byte("The time is: " + tm))
}
}
更便利的 DefaultServeMux 你可能已经在很多地方看到过 我花了很长时间才意识到 var DefaultServeMux = NewServeMux()
此外, 因此,作为最后一个步骤,我们使用 //File: main.go
package main
import (
"log"
"net/http"
"time"
)
func timeHandler(format string) http.Handler {
fn := func(w http.ResponseWriter,r *http.Request) {
tm := time.Now().Format(format)
w.Write([]byte("The time is: " + tm))
}
return http.HandlerFunc(fn)
}
func main() {
// Note that we skip creating the ServeMux...
var format string = time.RFC1123
th := timeHandler(format)
// We use http.Handle instead of mux.Handle...
http.Handle("/time",th)
log.Println("Listening...")
// And pass nil as the handler to ListenAndServe.
http.ListenAndServe(":3000",nil)
}
转自:http://www.52php.cn/article/p-mrunsgzy-c.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Grails框架优劣势分析及同类比较
- delphi – 删除备忘录中的最后一个空白行
- 使用Delphi创建DLL时应该遵循哪些原则在其他Delphi版本中运
- php – Laravel CRON或事件进程通过长时间轮询响应api请求
- php – Laravel ORM友谊关系,无重复
- 创建TRESTClient时出错:“没有注册带有guid [{}]的接口的对
- openrestry简介&安装&Hello World(1)
- kylin Build过程问题排查:17 Step Name: Build Cube In-Me
- perlbrew和local :: lib在同一时间?
- Perl并行迭代2个数组的方式