欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

Go語言Web基礎(chǔ)--Go如何使得Web工作 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當前位置>首頁 » 新聞資訊 » 網(wǎng)站建設 >

Go語言Web基礎(chǔ)--Go如何使得Web工作

發(fā)表時間:2018-7-22

發(fā)布人:葵宇科技

瀏覽次數(shù):92

Go搭建一個Web服務器

前面小節(jié)已經(jīng)介紹了Web是基于http協(xié)議的一個服務,Go語言里面提供了一個完善的net/http包,通過http包可以很方便的就搭建起來一個可以運行的Web服務。同時使用這個包能很簡單地對Web的路由,靜態(tài)文件,模版,cookie等數(shù)據(jù)進行設置和操作。

http包建立Web服務器

package main

import (
    "fmt"
    "net/http"
    "strings"
    "log"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()  //解析參數(shù),默認是不會解析的
    fmt.Println(r.Form)  //這些信息是輸出到服務器端的打印信息
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["url_long"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, "Hello astaxie!") //這個寫入到w的是輸出到客戶端的
}

func main() {
    http.HandleFunc("/", sayhelloName) //設置訪問的路由
    err := http.ListenAndServe(":9090", nil) //設置監(jiān)聽的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

上面這個代碼,我們build之后,然后執(zhí)行web.exe,這個時候其實已經(jīng)在9090端口監(jiān)聽http鏈接請求了。

在瀏覽器輸入http://localhost:9090

可以看到瀏覽器頁面輸出了Hello astaxie!

可以換一個地址試試:http://localhost:9090/?url_long=111&url_long=222

看看瀏覽器輸出的是什么,服務器輸出的是什么?

在服務器端輸出的信息如下:

我們看到上面的代碼,要編寫一個Web服務器很簡單,只要調(diào)用http包的兩個函數(shù)就可以了。

如果你以前是PHP程序員,那你也許就會問,我們的nginx、apache服務器不需要嗎?Go就是不需要這些,因為他直接就監(jiān)聽tcp端口了,做了nginx做的事情,然后sayhelloName這個其實就是我們寫的邏輯函數(shù)了,跟php里面的控制層(controller)函數(shù)類似。

如果你以前是Python程序員,那么你一定聽說過tornado,這個代碼和他是不是很像,對,沒錯,Go就是擁有類似Python這樣動態(tài)語言的特性,寫Web應用很方便。

如果你以前是Ruby程序員,會發(fā)現(xiàn)和ROR的/script/server啟動有點類似。

我們看到Go通過簡單的幾行代碼就已經(jīng)運行起來一個Web服務了,而且這個Web服務內(nèi)部有支持高并發(fā)的特性,我將會在接下來的兩個小節(jié)里面詳細的講解一下Go是如何實現(xiàn)Web高并發(fā)的。


Go如何使得Web工作

前面介紹了如何通過Go搭建一個Web服務,我們可以看到簡單應用一個net/http包就方便的搭建起來了。那么Go在底層到底是怎么做的呢?萬變不離其宗,Go的Web服務工作也離不開我們前面介紹的Web工作方式。

web工作方式的幾個概念

以下均是服務器端的幾個概念

  • Request:用戶請求的信息,用來解析用戶的請求信息,包括post、get、cookie、url等信息
  • Response:服務器需要反饋給客戶端的信息
  • Conn:用戶的每次請求鏈接
  • Handler:處理請求和生成返回信息的處理邏輯

分析http包運行機制

如下圖所示,是Go實現(xiàn)Web服務的工作模式的流程圖

http包執(zhí)行流程:

  1. 創(chuàng)建Listen Socket, 監(jiān)聽指定的端口, 等待客戶端請求到來。

  2. Listen Socket接受客戶端的請求, 得到Client Socket, 接下來通過Client Socket與客戶端通信。

  3. 處理客戶端的請求, 首先從Client Socket讀取HTTP請求的協(xié)議頭, 如果是POST方法, 還可能要讀取客戶端提交的數(shù)據(jù), 然后交給相應的handler處理請求, handler處理完畢準備好客戶端需要的數(shù)據(jù), 通過Client Socket寫給客戶端。

這整個的過程里面我們只要了解清楚下面三個問題,也就知道Go是如何讓Web運行起來了

  • 如何監(jiān)聽端口?
  • 如何接收客戶端請求?
  • 如何分配handler?

Go是通過一個函數(shù)ListenAndServe來處理這些事情的,這個底層其實這樣處理的:初始化一個server對象,然后調(diào)用了net.Listen("tcp", addr),也就是底層用TCP協(xié)議搭建了一個服務,然后監(jiān)控我們設置的端口。

下面代碼來自Go的http包的源碼,通過下面的代碼我們可以看到整個的http處理過程:

func (srv *Server) Serve(l net.Listener) error {
    defer l.Close()
    var tempDelay time.Duration // how long to sleep>監(jiān)控之后如何接收客戶端的請求呢?上面代碼執(zhí)行監(jiān)控端口之后,調(diào)用了srv.Serve(net.Listener)函數(shù),這個函數(shù)就是處理接收客戶端的請求信息。這個函數(shù)里面起了一個for{},首先通過Listener接收請求,其次創(chuàng)建一個Conn,最后單獨開了一個goroutine,把這個請求的數(shù)據(jù)當做參數(shù)扔給這個conn去服務:go c.serve()。這個就是高并發(fā)體現(xiàn)了,用戶的每一次請求都是在一個新的goroutine去服務,相互不影響。

那么如何具體分配到相應的函數(shù)來處理請求呢?conn首先會解析request:c.readRequest(),然后獲取相應的handler:handler := c.server.Handler,也就是我們剛才在調(diào)用函數(shù)ListenAndServe時候的第二個參數(shù),我們前面例子傳遞的是nil,也就是為空,那么默認獲取handler = DefaultServeMux,那么這個變量用來做什么的呢?對,這個變量就是一個路由器,它用來匹配url跳轉(zhuǎn)到其相應的handle函數(shù),那么這個我們有設置過嗎?有,我們調(diào)用的代碼里面第一句不是調(diào)用了http.HandleFunc("/", sayhelloName)嘛。這個作用就是注冊了請求/的路由規(guī)則,當請求uri為"/",路由就會轉(zhuǎn)到函數(shù)sayhelloName,DefaultServeMux會調(diào)用ServeHTTP方法,這個方法內(nèi)部其實就是調(diào)用sayhelloName本身,最后通過寫入response的信息反饋到客戶端。

詳細的整個流程如下圖所示:

至此我們的三個問題已經(jīng)全部得到了解答,你現(xiàn)在對于Go如何讓Web跑起來的是否已經(jīng)基本了解呢?


End