解析Go 標(biāo)準(zhǔn)庫(kù) http.FileServer 實(shí)現(xiàn)靜態(tài)文件服務(wù)
http.FileServer 方法屬于標(biāo)準(zhǔn)庫(kù) net/http,返回一個(gè)使用 FileSystem 接口 root 提供文件訪問服務(wù)的 HTTP 處理器。可以方便的實(shí)現(xiàn)靜態(tài)文件服務(wù)器。
http.ListenAndServe(":8080", http.FileServer(http.Dir("/files/path")))
訪問 http://127.0.0.1:8080,即可看到類似 Nginx 中 autoindex 目錄瀏覽功能。
源碼解析
我們現(xiàn)在開始將上述的那僅有的一行代碼進(jìn)行剖析,看看到底是如何實(shí)現(xiàn)的。源碼中英文注釋也比較詳細(xì),可以參考。
我們先看 http.Dir(),再看 http.FileServer(),而 http.ListenAndServe()
監(jiān)聽 TCP 端口并提供路由服務(wù),此處不贅述。
http.Dir()
從以下源碼我們可以看出,type Dir string 實(shí)現(xiàn)了 type FileSystem interface 的接口函數(shù) Open,http.Dir("/") 實(shí)際返回的是 http.Dir 類型,將字符串路徑轉(zhuǎn)換成文件系統(tǒng)。
// 所屬文件: src/net/http/fs.go, 26-87行 type Dir string func (d Dir) Open(name string) (File, error) { // ... } type FileSystem interface { Open(name string) (File, error) } http.FileServer() http.FileServer() 方法返回的是 fileHandler 實(shí)例,而 fileHandler 結(jié)構(gòu)體實(shí)現(xiàn)了 Handler 接口的方法 ServeHTTP()。ServeHTTP 方法內(nèi)的核心是 serveFile() 方法。 // 所屬文件: src/net/http/fs.go, 690-716行 type fileHandler struct { root FileSystem } func FileServer(root FileSystem) Handler { return &fileHandler{root} } func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) { upath := r.URL.Path if !strings.HasPrefix(upath, "/") { upath = "/" + upath r.URL.Path = upath } serveFile(w, r, f.root, path.Clean(upath), true) } // 所屬文件: src/net/http/server.go, 82行 type Handler interface { ServeHTTP(ResponseWriter, *Request) }
serveFile()
方法判斷,如果訪問路徑是目錄,則列出目錄內(nèi)容,如果是文件則使用 serveContent()
方法輸出文件內(nèi)容。serveContent()
方法則是個(gè)讀取文件內(nèi)容并輸出的方法,此處不再貼代碼。
// 所屬文件: src/net/http/fs.go, 540行 // name is '/'-separated, not filepath.Separator. func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) { // 中間代碼已省略 if d.IsDir() { if checkIfModifiedSince(r, d.ModTime()) == condFalse { writeNotModified(w) return } w.Header().Set("Last-Modified", d.ModTime().UTC().Format(TimeFormat)) dirList(w, r, f) return } // serveContent will check modification time sizeFunc := func() (int64, error) { return d.Size(), nil } serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f) }
支持子目錄路徑
http.StripPrefix()
方法配合 http.Handle()
或 http.HandleFunc()
可以實(shí)現(xiàn)帶路由前綴的文件服務(wù)。
package main import ( "net/http" "fmt" ) func main() { http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp")))) err := http.ListenAndServe(":8080", nil) if err != nil { fmt.Println(err) } }
總結(jié)
以上所述是小編給大家介紹的解析Go 標(biāo)準(zhǔn)庫(kù) http.FileServer 實(shí)現(xiàn)靜態(tài)文件服務(wù),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Go語言操作mysql數(shù)據(jù)庫(kù)簡(jiǎn)單例子
- Golang的os標(biāo)準(zhǔn)庫(kù)中常用函數(shù)的整理介紹
- 完美解決golang go get私有倉(cāng)庫(kù)的問題
- Golang標(biāo)準(zhǔn)庫(kù)syscall詳解(什么是系統(tǒng)調(diào)用)
- 深入解析Go語言的io.ioutil標(biāo)準(zhǔn)庫(kù)使用
- Go編寫定時(shí)器與定時(shí)任務(wù)詳解(附第三方庫(kù)gocron用法)
- 解決Go語言數(shù)據(jù)庫(kù)中null值的問題
- 一步步教你打造高效可靠的Go庫(kù)
相關(guān)文章
Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換
在軟件開發(fā)的世界里,數(shù)據(jù)類型轉(zhuǎn)換是一項(xiàng)基礎(chǔ)而重要的技能,尤其在Go語言這樣類型嚴(yán)格的語言中,正確高效地進(jìn)行類型轉(zhuǎn)換對(duì)于性能優(yōu)化和代碼質(zhì)量至關(guān)重要,本文給大家介紹了Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換,需要的朋友可以參考下2024-02-02Golang?IOT中的數(shù)據(jù)序列化與解析過程
這篇文章主要介紹了Golang?IOT中的數(shù)據(jù)序列化與解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05一文帶你了解Go語言fmt標(biāo)準(zhǔn)庫(kù)輸出函數(shù)的使用
這篇文章主要為大家詳細(xì)介紹了Go語言中 fmt 標(biāo)準(zhǔn)庫(kù)輸出函數(shù)的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12