go语言服务器运行,Go语言实现Web服务器
使用Go語言的庫非常容易實現一個Web服務器,用來響應像fetch那樣的客戶端請求。本節將展示一個迷你服務器,返回訪問服務器的URL的路徑部分。例如,如果請求的URL是http://localhost:8000/hello,響應將是URL.Path="/hello"。
//server1.go這是一個迷你回聲服務器packagemainimport("fmt""log""net/http")funcmain(){http.HandleFunc("/",handler)//回聲請求調用處理程序log.Fatal(http.ListenAndServe("localhost:8000",nil))}//處理程序回顯請求URLr的路徑部分funchandler(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"URL.Path=%qn",r.URL.Path)}
這個程序只有寥寥幾行代碼,因為庫函數做了大部分工作。main函數將一個處理函數和以“/”開頭的URL鏈接在一起,代表所有的URL使用這個函數處理,然后啟動服務器監聽進入8000端口處的請求。
一個請求由一個http.Request類型的結構體表示,它包含很多關聯的域,其中一個是所請求的URL。當一個請求到達時,它被轉交給處理函數,并從請求的URL中提取路徑部分(/hello),使用fmt.Printf格式化,然后作為響應發送回去。
讓我們在后臺啟動服務器。在MacOSX或者Linux上,在命令行后添加一個&符號;在微軟Windows上,不需要&符號,而需要單獨開啟一個獨立的命令行窗口。
$gorunsrc/gopl.io/chl/serverl/main.go&
可以從命令行發起客戶請求:
$gobuildgopl.io/ch5/fetch
$./fetchhttp://localhost:8000
URL.Path=T
$./fetchhttp://localhost:8000/help
URL.Path="/help"
另外,還可以通過瀏覽器進行訪問,如下圖所示。
圖:來自回聲服務器的響應
為服務器添加功能很容易。一個有用的擴展是一個特定的URL,它返回某種排序的狀態。例如,這個版本的程序完成和回聲服務器一樣的事情,但同時返回請求的數量;URL/count請求返回到現在為止的個數,去掉/count請求本身:
//server2.go這是一個迷你的回聲和計數器服務器packagemainimport("fmt""log""net/http""sync")varmusync.Mutexvarcountintfuncmain(){http.HandleFunc("/",handler)http.HandleFunc("/count",counter)log.Fatal(http.ListenAndServe("localhost:8000",nil))}//處理程序回顯請求的URL的路徑部分funchandler(whttp.ResponseWriter,r*http.Request){mu.Lock()count++mu.Unlock()fmt.Fprintf(w,"URL.Path=%qn",r.URL.Path)}//counter回顯目前為止調用的次數funccounter(whttp.ResponseWriter,r*http.Request){mu.Lock()fmt.Fprintf(w,"Count%dn",count)mu.Unlock()}
這個服務器有兩個處理函數,通過請求的URL來決定哪一個被調用:請求/count調用counter,其他的調用handler。以“/”結尾的處理模式匹配所有含有這個前綴的URL。在后臺,對于每個傳入的請求,服務器在不同的goroutine中運行該處理函數,這樣它可以同時處理多個請求。
然而,如果兩個并發的請求試圖同時更新計數值count,它可能會不一致地增加,程序會產生一個嚴重的競態bug。為避免該問題,必須確保最多只有一個goroutine在同一時間訪問變量,這正是mu.Lock()和mu.Unlock()語句的作用。
作為一個更完整的例子,處理函數可以報告它接收到的消息頭和表單數據,這樣可以方便服務器審查和調試請求:
//處理程序回顯HTTP請求funchandler(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"%s%s%sn",r.Method,r.URL,r.Proto)fork,v:=ranger.Header{fmt.Fprintf(w,"Header[%q]=%qn",k,v)}fmt.Fprintf(w,"Host=%qn",r.Host)fmt.Fprintf(w,"RemoteAddr=%qn",r.RemoteAddr)iferr:=r.ParseForm();err!=nil{log.Print(err)}fork,v:=ranger.Form{fmt.Fprintf(w,"Form[%q]=%qn",k,v)}}
這里使用http.Request結構體的成員來產生類似下面的輸出:
GET/?q=queryHTTP/1.1
Header["Accept-Encoding"]=["gzip,deflate,sdch"]
Header["Accept-Language"]=["en-US,en;q=0.8"]
Header["Connection"]=["keep-alive"]
Header["Accept"]=["text/html,application/xhtml+xml,application/xml;…"]
Header["User-Agent"]=["Mozilla/5.0(Macintosh;IntelMacOSX10_7_5)…"]
Host="localhost:8000"
RemoteAddr="127.0.0.1:59911"
Form["q"]=["query"]
注意這里是如何在if語句中嵌套調用ParseForm的。Go允許一個簡單的語句(如一個局部變量聲明)跟在if條件的前面,這在錯誤處理的時候特別有用。也可以這樣寫:
err:=r.ParseForm()
iferr!=nil{
log.Print(err)
}
這些程序中,我們看到了作為輸出流的三種非常不同的類型。fetch程序復制HTTP響應到文件os.Stdout,像lissajous一樣;fetchall程序通過將響應復制到ioutil.Discard中進行丟棄(在統計其長度時);Web服務器使fmt.Fprintf通過寫入http.Responsewriter來讓瀏覽器顯示。
盡管三種類型細節不同,但都滿足一個通用的接口(interface),該接口允許它們按需使用任何一種輸出流。該接口稱為io.Writer。
我們來看一下整合Web服務器和lissajous函數是一件多么容易的事情,這樣GIF動畫將不再輸出到標準輸出而是HTTP客戶端。簡單添加這些行到Web服務器:
handler:=func(whttp.ResponseWriter,r*http.Request){
lissajous(w)
}
http.HandleFunc("/",handler)
或者也可以:
http.HandleFunc("/",func(whttp.ResponseWriter,r*http.Request){
lissajous(w)
})
上面HandleFunc函數中立即調用的第二個參數是函數字面量,這是一個在該場景中使用它時才定義的匿名函數。
一旦完成這個改變,就可以通過瀏覽器訪問http://localhost:8000。每次加載頁面,將看到一個類似下圖的動畫。
圖:瀏覽器中的動態利薩茹圖形
總結
以上是生活随笔為你收集整理的go语言服务器运行,Go语言实现Web服务器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公司资质备案怎么办理(公司资质备案)
- 下一篇: 多媒体计算机属于哪种教学,多媒体计算机属