golang學習之negroni對於第三方中介軟體的使用分析
negroni本身是一箇中間件,不過它也提供了拓展,以幫助我們更簡單地實現自己想要的功能的中介軟體。那麼,我們究竟該如何實現中介軟體,才能能夠封裝到negroni中,從而通過negroni來呼叫呢?可以通過一個簡單的例子分析:
package main
import (
"fmt"
"net/http"
"github.com/urfave/negroni"
"github.com/phyber/negroni-gzip/gzip"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page!" )
})
n := negroni.Classic() //建立一個negroni
n.Use(gzip.Gzip(gzip.DefaultCompression))
n.UseHandler(mux)
n.Run(":3000")
}
我們從negroni建立之後開始分析。n.UseHandler(mux)函式:
n.UseHandler(mux)
+func (n *Negroni) UseHandler(handler http.Handler)
|n.Use(Wrap(handler))
+func Wrap(handler http.Handler ) Handler
|return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+func (n *Negroni) Use(handler Handler)
|n.handlers = append(n.handlers, handler)
|n.middleware = build(n.handlers)
+func build(handlers []Handler ) middleware
|return middleware{handlers[0], &next}
呼叫n.UseHandler(mux)函式的過程中,同樣也呼叫了n.Use()函式。說明negroni對於第三方中介軟體的使用是從n.UseHandler開始的。
接下來,一起來分析追蹤過程中遇到的函式:
1. UseHandler
該函式返回將handler傳遞給Wrap()函式
func (n *Negroni) UseHandler(handler http.Handler) {
n.Use(Wrap(handler))
}
2. Wrap
該函式對handler進行封裝,程式設計固定format的handler。
func Wrap(handler http.Handler) Handler {
return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
handler.ServeHTTP(rw, r)
next(rw, r)
})
}
3. Use
該函式則將handler新增到Negroni結構體中。其中,midlleware是一個連結串列。
func (n *Negroni) Use(handler Handler) {
if handler == nil {
panic("handler cannot be nil")
}
n.handlers = append(n.handlers, handler)
n.middleware = build(n.handlers)
}
+-----------------------------------------+
type Negroni struct {
middleware middleware
handlers []Handler
}
type middleware struct {
handler Handler
next *middleware
}
4. build
如果你瞭解C/C++,這個函式很好理解。它僅僅是一個迭代函式,實現了middleware連結串列的構建。
func build(handlers []Handler) middleware {
var next middleware
if len(handlers) == 0 {
return voidMiddleware()
} else if len(handlers) > 1 {
next = build(handlers[1:])
} else {
next = voidMiddleware()
}
return middleware{handlers[0], &next}
}
5. 對ServerHTTP的處理
同時,我們也要清楚Handler是一個介面,一個Handler物件必須實現Handler介面。Handler介面定義如下:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
negroni對ServeHTTP做了哪些處理呢?通過以下三個函式可以瞭解:
//函式型別,使用HandleFunc會呼叫
//func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)的實現
type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
//呼叫函式實現
func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
h(rw, r, next)
}
//實現ServerHTTP的封裝
func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
}
接下來,我們追蹤n.Run(“:3000”)函式:
n.Run(":3000")
+func (n *Negroni) Run(addr ...string)
|finalAddr := detectAddress(addr...)
+func detectAddress(addr ...string) string
|l.Fatal(http.ListenAndServe(finalAddr, n))
+func ListenAndServe(addr string, handler Handler) error
|......
negroni.Run解析address後,最終呼叫了http.ListenAndServe來實現伺服器。這一步,才最終完成了伺服器的搭建;所有的handler都交付給了http.ListenAndServe去實現。
關於negroni對於第三方中介軟體的使用就分析到這裡了。
相關推薦
golang學習之negroni對於第三方中介軟體的使用分析
negroni本身是一箇中間件,不過它也提供了拓展,以幫助我們更簡單地實現自己想要的功能的中介軟體。那麼,我們究竟該如何實現中介軟體,才能能夠封裝到negroni中,從而通過negroni來呼叫呢?可以通過一個簡單的例子分析: package main
golang 學習之語言切片Slice Range範圍 MAP 遞迴函式
Go 語言切片是對陣列的抽象。 Go 陣列的長度不可改變,在特定場景中這樣的集合就不太適用,Go中提供了一種靈活,功能強悍的內建型別切片(“動態陣列”),與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。 定義一個未指定大小的切片
golangWeb框架---github.com/gin-gonic/gin學習七(重定向、中介軟體Goroutines、http自定義配置)
重定向 package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { router := gin.Default() router.GET("/raw",
Golang學習之Goroutines和 channel
Goroutines 在Go語言中,每一個併發的執行單元叫作一個goroutine,可以簡單地把goroutine類比作一個執行緒,本質上是一個協程。但它與協程有倆點不同: goroutinue可以實現並行,也就是說,多個協程可以在多個處理器同時跑。而協程同一
GOLANG 學習之陣列
陣列是值型別 [10]int和[20]int是不同型別 呼叫func f(arr [5]int)會拷貝陣列 在go語言中一般不直接使用陣列 申明一個數組 // variable_name-變數名稱
golang學習之net/http 原始碼分析
2018年11月15日 18:30:57 焰絕 閱讀數:4 個人分類: 服務計算
【Java進階面試系列之五】訊息中介軟體叢集崩潰,如何保證百萬生產資料不丟失?【石杉的架構筆記】
歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! “上一篇講訊息中介軟體的文章《扎心!線上服務宕機時,如何保證資料100%不丟失?》,初步給大家介紹了一個在生產環境中可能遇到的問題,就是你的消費者服務可能會宕機,一旦宕機,你就需要考慮是否會導致
Golang學習之從命令列讀取config配置檔案
Golang學習筆記之從命令列讀取配置檔案 注:本文為個人學習筆記,如果你看到本文有收穫請給予點贊支援,如果發現錯誤,請告知,謝謝! 應用場景 很多時候,我們都是講伺服器環境配置引數在程式碼中寫死,然後隨著程式碼打不同環境的包檔案 ,那麼如何才能動態載入我們所需要的配置檔案呢?這個時候,是
Golang學習之net包介紹
與大多數語言一樣,Go的標準庫很全,因為Go的出現本來就是為了網路通訊的高併發實現,所以其相關的網路庫封裝得更簡潔,更Readable。 這裡來大致介紹幾個網路庫,掌握了學習方法,那麼只要裡面有那個功能,你就能找到並快讀查閱原始碼
Golang學習之在專案中遇到的幾個常用的方法
1、TempFile TempFile 在 dir 目錄中建立一個以 prefix 為字首的臨時檔案,並將其以讀 寫模式開啟。返回建立的檔案物件和遇到的錯誤。 如果 dir 為空,則在預設的臨時目錄中建立檔案(
golang學習之安裝環境
安裝: 1. 官網安裝最新的golang安裝包 我的是win7下載的是go1.4.2.windows-amd64 配置環境變數 export GOROOT=$HOME/go export PATH=$PATH:$GOROOT/bin 再配置GOPATH,路
Golang學習之GOROOT、PATH、GOPATH及go get
1. GOROOT GOPATH 及 PATH 設定 a.新增系統變數GOROOT:安裝完Go第一件事就是設定GOROOT。例如我的Go安裝在C:\Go目錄,則要設定 GOROOT = C:\Go b.修改環境變數PATH:將%GOROOT%\bin加到環境變數PATH
Django元件之使用者認證和中介軟體
使用者認證元件 功能:用session記錄登入驗證狀態 前提:使用者表 django自帶的auth_user 建立超級使用者python manage.py createsuperuser API 如下 一、 auth模組 1: from django.contrib import
golang學習之指標、記憶體分配
1 func pointer_test() { 2 //空指標,輸出為nil 3 var p *int 4 fmt.Printf("p: %v\n", p) 5 //指向區域性變數,變數值初始為0 6 var i int 7 p = &i
【React全家桶入門之十三】Redux中介軟體與非同步action
在上一篇中我們瞭解到,更新Redux中狀態的流程是這樣的:action -> reducer -> new state。 文中也講到,action是一個普通的javascript物件、reducer是一個普通的方法,在reducer中根據當前的st
【轉】Golang學習之同一個package中函式互相呼叫的問題
問題程式碼如下 a.go: package main func main(){ Test() } b.go: package main import "fmt" func Test(){ fmt.Println("Hello World!") } 這
Golang 學習之路一:開發環境搭建
Golang 學習:開發環境搭建 一、下載適合本機的Golang版本 注意對應好自己PC 的system. Windows 直接下載對應的msi安裝即可,Linux注意發行版本。 本文L
效能測試之中介軟體分析與調優
目前招聘效能測試工程師,都要求要了解中介軟體,中介軟體也是效能測試工程師必須要掌握的一大節點,所以有必要對中介軟體的相關含義及架構有一定的瞭解,那麼問題來了,中介軟體到底是什麼?在整個系統中承擔一個什麼樣的角色? 中介軟體定義 中介軟體是一類連線
Golang學習之標準庫io/ioutil,讀取檔案,生成臨時目錄/檔案
1.讀取目錄 list, err := ioutil.ReadDir("DIR")//要讀取的目錄地址DIR,得到列表 if err != nil { fmt.Println("read dir error") return } for _,
Golang 學習之路九:介面(Interface)
Golang學習之路:介面(interface) 一、前言 Go 語言和傳統的OO語言概念思想上不同,它在語法上不支援類與整合的概念。但是為了實現類似於C++等語言中多型行為,Go語言引入了interface型別,實現了類似於多型的功能。注意inte