内容简介:几个官方的例子,拿来练习一下,wc, 体会到了 go http 包的强大之处:
https://golang.org/pkg/net/http/
几个官方的例子,拿来练习一下,wc, 体会到了 go http 包的强大之处:
下面是一些例子,来主要讲解下面的几个函数
FileServer
FileServer (DotFileHiding)
FileServer (StripPrefix)
Get
Handle
HandleFunc
Hijacker
ListenAndServe
ListenAndServeTLS
NotFoundHandler
ResponseWriter (Trailers)
ServeMux.Handle
Server.Shutdown
主体结构是:
func main(){ FileServer() ... }
我把每个函数的例子,封装为一个函数 然后放在 main 函数里面执行一下。main 都是重复的,所以就不贴代码了。(联系 采用 subline,炒鸡方便)
-
FileServer
func FileServer(root FileSystem) Handler
这个函数也是很牛逼, 主要是可以把文件路径映射为 url 路由。
https://golang.org/pkg/net/http/#FileServer
实现原理:
https://shockerli.net/post/golang-pkg-http-file-server/使用 FileSystem 接口 root 提供文件访问服务的 HTTP 处理器。可以方便的实现静态文件服务器
func FileServer(){ http.ListenAndServe(":8081", http.FileServer(http.Dir("F:/go/"))) }
运行效果:
注意多次运行,可能需要更改端口号
点击 go_practice 链接(文件夹)
点击 http_pkg.go
上面是个简单的 可以展示文件目录的功能,go 底层,帮我们实现了 文件读取和展示。
支持子目录路径
只是比上面多了个 自定义路由前缀
http.StripPrefix() 方法配合 http.Handle() 或 http.HandleFunc() 可以实现带路由前缀的文件服务。
func FileServer(){ // // http.ListenAndServe(":8081", http.FileServer(http.Dir("F:/go/"))) http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("F:/go/")))) http.ListenAndServe(":8082", nil) }
运行效果:
会比第一个程序多一个 tmpfiles 路径前缀
-
Handle
func Handle(pattern string, handler Handler)
路由匹配处理函数, 要实现 Handler 接口的 ServeHTTP(w http.ResponseWriter, r *http.Request) 方法
package main import ( "fmt" "log" "net/http" "sync" ) type countHandler struct { mu sync.Mutex // guards n n int } func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.mu.Lock() defer h.mu.Unlock() h.n++ fmt.Fprintf(w, "count is %d\n", h.n) } func main() { http.Handle("/count", new(countHandler)) log.Fatal(http.ListenAndServe(":8080", nil)) }
-
HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
和 Handle 几乎一样,唯一不同的是参数不一样,这个是自己定义一个
xx(w http.ResponseWriter, r *http.Request) 这样的函数,儿不必叫 ServeHTTP 名字,因为 HandleFunc 函数第二个参数是 直接一个函数类型,二不是 有ServeHTTP 函数的 Handler 接口类型
func simple_server(){ http.HandleFunc("/my_name", name_haddler) http.HandleFunc("/url", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello, %q</h1>", html.EscapeString(r.URL.Path)) }) http.ListenAndServe(":8080", nil) } func name_haddler(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "<h1>hello yxl</h1>") }
-
ListenAndServe
func ListenAndServe(addr string, handler Handler) error
第二个参数通常为 nil, 在这种情况下,使用DefaultServeMux。
func simple_server(){ http.HandleFunc("/my_name", name_haddler) http.HandleFunc("/url", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello, %q</h1>", html.EscapeString(r.URL.Path)) }) http.ListenAndServe(":8080", nil) } func name_haddler(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "<h1>hello yxl</h1>") }
-
ListenAndServeTLS
func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error
ListenAndServe HTTPS 版本
-
NotFoundHandler
404 对应的处理
func NotFoundHandler() Handler
func NotFoundHandler(){ // 404 对应的处理 mux.Handle("/resources", http.NotFoundHandler()) }
-
ResponseWriter
一个接口
定义源码如下:
<pre>type ResponseWriter interface { // Header returns the header map that will be sent by // WriteHeader. The Header map also is the mechanism with which // Handlers can set HTTP trailers. // // Changing the header map after a call to WriteHeader (or // Write) has no effect unless the modified headers are // trailers. // // There are two ways to set Trailers. The preferred way is to // predeclare in the headers which trailers you will later // send by setting the "Trailer" header to the names of the // trailer keys which will come later. In this case, those // keys of the Header map are treated as if they were // trailers. See the example. The second way, for trailer // keys not known to the Handler until after the first Write, // is to prefix the Header map keys with the TrailerPrefix // constant value. See TrailerPrefix. // // To suppress automatic response headers (such as "Date"), set // their value to nil. Header() [Header](https://golang.org/pkg/net/http/#Header) // Write writes the data to the connection as part of an HTTP reply. // // If WriteHeader has not yet been called, Write calls // WriteHeader(http.StatusOK) before writing the data. If the Header // does not contain a Content-Type line, Write adds a Content-Type set // to the result of passing the initial 512 bytes of written data to // DetectContentType. Additionally, if the total size of all written // data is under a few KB and there are no Flush calls, the // Content-Length header is added automatically. // // Depending on the HTTP protocol version and the client, calling // Write or WriteHeader may prevent future reads on the // Request.Body. For HTTP/1.x requests, handlers should read any // needed request body data before writing the response. Once the // headers have been flushed (due to either an explicit Flusher.Flush // call or writing enough data to trigger a flush), the request body // may be unavailable. For HTTP/2 requests, the Go HTTP server permits // handlers to continue to read the request body while concurrently // writing the response. However, such behavior may not be supported // by all HTTP/2 clients. Handlers should read before writing if // possible to maximize compatibility. Write([][byte](https://golang.org/pkg/builtin/#byte)) ([int](https://golang.org/pkg/builtin/#int), [error](https://golang.org/pkg/builtin/#error)) // WriteHeader sends an HTTP response header with the provided // status code. // // If WriteHeader is not called explicitly, the first call to Write // will trigger an implicit WriteHeader(http.StatusOK). // Thus explicit calls to WriteHeader are mainly used to // send error codes. // // The provided code must be a valid HTTP 1xx-5xx status code. // Only one header may be written. Go does not currently // support sending user-defined 1xx informational headers, // with the exception of 100-continue response header that the // Server sends automatically when the Request.Body is read. WriteHeader(statusCode [int](https://golang.org/pkg/builtin/#int)) }</pre>
其他的暂时就不讲了,太难了,老铁
完整总结的代码(其实和上面一样的):
package main /* http 包的练习 */ import ( "fmt" "net/http" "io/ioutil" "html" _ "log" ) func easy_test(url string){ resp, err := http.Get(url) if err != nil{ fmt.Printf("%v", err) return } defer resp.Body.Close() // 入站是当前内存区域的 执行, 和主函数分开的,每个块内存都可以有自己的 压栈 defer fmt.Printf("请求函数执行结束") body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("%s", body) return } func simple_server(){ http.HandleFunc("/my_name", name_haddler) http.HandleFunc("/url", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<h1>Hello, %q</h1>", html.EscapeString(r.URL.Path)) }) http.ListenAndServe(":8080", nil) } func name_haddler(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "<h1>hello yxl</h1>") } // 事例 // FileServer // FileServer (DotFileHiding) // FileServer (StripPrefix) // Get // Handle // HandleFunc // Hijacker // ListenAndServe // ListenAndServeTLS // NotFoundHandler // ResponseWriter (Trailers) // ServeMux.Handle // Server.Shutdown // StripPrefix // FileServer func FileServer(root FileSystem) Handler func FileServer(){ http.ListenAndServe(":8081", http.FileServer(http.Dir("F:/go/"))) } // FileServer (DotFileHiding) func FileServer_DotFileHiding(){ // 这个看不懂啊 } // FileServer (StripPrefix) func FileServer_StripPrefix(){ // 这个就是子在 FileServer 基础上加了一个前缀路由地址 http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("F:/go/")))) http.ListenAndServe(":8082", nil) } // Get func Get(url string) (resp *Response, err error) func get(){ // 请求一个地址, 如果状态码是 30x x 是12378之一 就自动重定向,最多 10 次 // 参见 11 行 easy_test } // Handle func Handle(pattern string, handler Handler) func handle(){ // 就是添加路由,匹配对应一个函数酱紫 // 这个就暂时补贴代码了 // 路由匹配处理函数(结构体类型), 要实现 Handler 接口的 ServeHTTP(w http.ResponseWriter, r *http.Request) 方法 } // HandleFunc func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) func HandleFunc(){ // 和 Handle 几乎一样,唯一不同的是参数不一样,这个是自己定义一个 // xx(w http.ResponseWriter, r *http.Request) 这样的函数,儿不必叫 ServeHTTP 名字,因为 HandleFunc 函数第二个参数是 直接一个函数类型,二不是 有ServeHTTP 函数的 Handler 接口类型 // 参见 simple_server 24-37 行 } // ListenAndServe func ListenAndServe(addr string, handler Handler) error func ListenAndServe(){ // 参见 } // ListenAndServeTLS func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error func ListenAndServeTLS(){ // ListenAndServe HTTPS 版本 } // NotFoundHandler func NotFoundHandler() Handler func NotFoundHandler(){ // 404 对应的处理 mux.Handle("/resources", http.NotFoundHandler()) } // ResponseWriter interface func ResponseWriter(){ // 上面所有的 处理函数,都直接或者间接实现这个 函数了 // 如: func(w http.ResponseWriter, r *http.Request) // 还有 Handler 接口定义的 ServeHTTP(ResponseWriter, *Request) 函数(同包就省略了 http.) } // func (*ServeMux) ServeMux func (mux *ServeMux) Handle(pattern string, handler Handler) func ServeMux_ServeMux(){ // 这个不太懂 } // func (*Server) Shutdown func (srv *Server) Shutdown(ctx context.Context) error func Server_Shutdown(){ // 这个也不会 } // StripPrefix func StripPrefix(prefix string, h Handler) Handler func StripPrefix(){ // 删除请求的特定前缀 // 参见: FileServer_StripPrefix 70 行 } func main(){ // easy_test("https://sunrain.xyz") // simple_server() FileServer() }
欢迎关注我们的微信公众号,每天学习 Go 知识
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- [Vue 2.x Todo 教程练习参考答案] 标为完成练习参考答案
- [Vue 2.x Todo 教程练习参考答案] 添加todo练习参考答案
- [Vue 2.x Todo 教程练习参考答案] 入门仪式_Hello_Vue练习参考答案
- python二级练习(4)
- python二级练习(6)
- python二级练习(7)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Discrete Mathematics and Its Applications
Kenneth H Rosen / McGraw-Hill Science/Engineering/Math / 2003-04-22 / USD 132.81
Discrete Mathematics and its Applications is a focused introduction to the primary themes in a discrete mathematics course, as introduced through extensive applications, expansive discussion, and deta......一起来看看 《Discrete Mathematics and Its Applications》 这本书的介绍吧!