golang web基礎(chǔ)

大神的教程https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/03.0.md

https://www.yuque.com/liujunjie/pshhng/inyv2t

Web是基于http協(xié)議的一個服務(wù)湾宙,Go語言里面提供了一個完善的net/http包歌粥,通過http包可以很方便的搭建起來一個可以運行的Web服務(wù)襟士。同時使用這個包能很簡單地對Web的路由,靜態(tài)文件,模版,cookie等數(shù)據(jù)進行設(shè)置和操作材诽。

Web工作方式

HTTP協(xié)議

它通過HTTP協(xié)議與客戶端通信

HTTP是一種讓Web服務(wù)器與瀏覽器(客戶端)通過Internet發(fā)送與接收數(shù)據(jù)的協(xié)議,它建立在TCP協(xié)議之上渤昌,一般采用TCP的80端口。

HTTP協(xié)議是無狀態(tài)的澈驼,同一個客戶端的這次請求和上次請求是沒有對應(yīng)關(guān)系的辛燥,對HTTP服務(wù)器來說,它并不知道這兩個請求是否來自同一個客戶端。為了解決這個問題挎塌, Web程序引入了Cookie機制來維護連接的可持續(xù)狀態(tài)徘六。

HTTP協(xié)議是建立在TCP協(xié)議之上的

HTTP請求包(瀏覽器信息)

我們先來看看Request包的結(jié)構(gòu), Request包分為3部分,第一部分叫Request line(請求行), 第二部分叫Request header(請求頭),第三部分是body(主體)榴都。header和body之間有個空行待锈,請求包的例子所示:

GET /domains/example/ HTTP/1.1 ?//請求行: 請求方法 請求URI HTTP協(xié)議/協(xié)議版本

Host:www.iana.org ? ?//服務(wù)端的主機名

User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4 ? //瀏覽器信息

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //客戶端能接收的MIME

Accept-Encoding:gzip,deflate,sdch ?//是否支持流壓縮

Accept-Charset:UTF-8,*;q=0.5 ?//客戶端字符編碼集

//空行,用于分割請求頭和消息體

//消息體,請求資源參數(shù),例如POST傳遞的參數(shù)

HTTP響應(yīng)包(服務(wù)器信息)

我們再來看看HTTP的response包,他的結(jié)構(gòu)如下:

HTTP/1.1 200 OK ? ? ?//狀態(tài)行

Server: nginx/1.0.8 ? ? //服務(wù)器使用的WEB軟件名及版本

Date:Date: Tue, 30 Oct 2012 04:14:25 GMT ?//發(fā)送時間

Content-Type: text/html ? ?//服務(wù)器發(fā)送信息的類型

Transfer-Encoding: chunked ? //表示發(fā)送HTTP包是分段發(fā)的

Connection: keep-alive ? ?//保持連接狀態(tài)

Content-Length: 90 ? ? //主體內(nèi)容長度

//空行 用來分割消息頭和主體

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... //消息體

TCP/IP協(xié)議

客戶機通過TCP/IP協(xié)議建立到服務(wù)器的TCP連接

DNS服務(wù)器

瀏覽器會去請求DNS服務(wù)器嘴高,通過DNS獲取相應(yīng)的域名對應(yīng)的IP竿音,然后通過IP地址找到IP對應(yīng)的服務(wù)器后,要求建立TCP連接拴驮,等瀏覽器發(fā)送完HTTP Request(請求)包后春瞬,服務(wù)器接收到請求包之后才開始處理請求包,服務(wù)器調(diào)用自身服務(wù)莹汤,返回HTTP Response(響應(yīng))包快鱼;客戶端收到來自服務(wù)器的響應(yīng)后開始渲染這個Response包里的主體(body),等收到全部的內(nèi)容隨后斷開與該服務(wù)器之間的TCP連接纲岭。

DNS(Domain Name System)是“域名系統(tǒng)”的英文縮寫抹竹,是一種組織成域?qū)哟谓Y(jié)構(gòu)的計算機和網(wǎng)絡(luò)服務(wù)命名系統(tǒng),它用于TCP/IP網(wǎng)絡(luò)止潮,它從事將主機名或域名轉(zhuǎn)換為實際IP地址的工作窃判。

URL

(Uniform Resource Locator)是“統(tǒng)一資源定位符”的英文縮寫,用于描述一個網(wǎng)絡(luò)上的資源, 基本格式如下

scheme://host[:port#]/path/.../[?query-string][#anchor]

scheme ? ? ? ? 指定底層使用的協(xié)議(例如:http, https, ftp)

host ? ? ? ? ? HTTP服務(wù)器的IP地址或者域名

port# ? ? ? ? ?HTTP服務(wù)器的默認端口是80喇闸,這種情況下端口號可以省略袄琳。如果使用了別的端口,必須指明燃乍,例如 http://www.cnblogs.com:8080/

path ? ? ? ? ? 訪問資源的路徑

query-string ? 發(fā)送給http服務(wù)器的數(shù)據(jù)

anchor ? ? ? ? 錨

Go如何使得Web工作

幾個概念Request?Response?Conn?Handler

Request:用戶請求的信息唆樊,用來解析用戶的請求信息,包括post刻蟹、get逗旁、cookie、url等信息

Response:服務(wù)器需要反饋給客戶端的信息

Conn:用戶的每次請求鏈接

Handler:處理請求和生成返回信息的處理邏

分析http包運行機制

如何監(jiān)聽端口舆瘪?

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

如何接收客戶端請求召调?

調(diào)用了srv.Serve(net.Listener)函數(shù)膨桥,這個函數(shù)就是處理接收客戶端的請求信息蛮浑。這個函數(shù)里面起了一個for{},首先通過Listener接收請求国撵,其次創(chuàng)建一個Conn陵吸,最后單獨開了一個goroutine,把這個請求的數(shù)據(jù)當做參數(shù)扔給這個conn去服務(wù):go c.serve()介牙。這個就是高并發(fā)體現(xiàn)了,用戶的每一次請求都是在一個新的goroutine去服務(wù)澳厢,相互不影響环础。

如何分配handler?

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

Go的http包詳解

設(shè)置路由對應(yīng)的handle

//? ? http.HandleFunc("/", sayhelloName)// Handle registers the handler for the given pattern.// If a handler already exists for pattern, Handle panics.func(mux*ServeMux)Handle(patternstring,handlerHandler) {mux.mu.Lock()//鎖defermux.mu.Unlock()//解鎖ifpattern==""{panic("http: invalid pattern")? }ifhandler==nil{panic("http: nil handler")? }if_,exist:=mux.m[pattern];exist{panic("http: multiple registrations for "+pattern)? }ifmux.m==nil{mux.m=make(map[string]muxEntry)? }e:=muxEntry{h:handler,pattern:pattern}mux.m[pattern]=eifpattern[len(pattern)-1]=='/'{mux.es=appendSorted(mux.es,e)? }ifpattern[0]!='/'{mux.hosts=true}}

根據(jù)路由獲取對應(yīng)handle

//serverHandler{c.server}.ServeHTTP(w, w.req) 中調(diào)用 會判斷 sh.srv.Handler是否為空,如果為空就賦值為//DefaultServeMux 為公共變量ServeMux,//http.HandleFunc("/", sayhelloName) //設(shè)置訪問的路由 會將pattern設(shè)置到ServeMux的m? ? map[string]muxEntrytypeserverHandlerstruct{srv*Server}func(shserverHandler)ServeHTTP(rwResponseWriter,req*Request) {handler:=sh.srv.Handlerifhandler==nil{handler=DefaultServeMux}ifreq.RequestURI=="*"&&req.Method=="OPTIONS"{handler=globalOptionsHandler{}? }handler.ServeHTTP(rw,req)}typeServeMuxstruct{musync.RWMutexmmap[string]muxEntryes[]muxEntry// slice of entries sorted from longest to shortest.hostsbool// whether any patterns contain hostnames}

設(shè)置監(jiān)聽端

ln,err:=net.Listen("tcp",addr)c:=srv.newConn(rw)// A conn represents the server side of an HTTP connection.c.setState(c.rwc,StateNew)// before Serve can returngoc.serve(ctx)serverHandler{c.server}.ServeHTTP(w,w.req)

go c.serve(ctx) 是一個for循環(huán)里面,接收端口傳過的信息

// Serve accepts incoming connections on the Listener l, creating a// new service goroutine for each. The service goroutines read requests and// then call srv.Handler to reply to them.//// HTTP/2 support is only enabled if the Listener returns *tls.Conn// connections and they were configured with "h2" in the TLS// Config.NextProtos.//// Serve always returns a non-nil error and closes l.// After Shutdown or Close, the returned error is ErrServerClosed.func(srv*Server)Serve(lnet.Listener)error{iffn:=testHookServerServe;fn!=nil{fn(srv,l)// call hook with unwrapped listener}l=&onceCloseListener{Listener:l}deferl.Close()iferr:=srv.setupHTTP2_Serve();err!=nil{returnerr}if!srv.trackListener(&l,true) {returnErrServerClosed}defersrv.trackListener(&l,false)vartempDelaytime.Duration// how long to sleep on accept failurebaseCtx:=context.Background()// base is always background, per Issue 16220ctx:=context.WithValue(baseCtx,ServerContextKey,srv)for{rw,e:=l.Accept()ife!=nil{select{case<-srv.getDoneChan():returnErrServerCloseddefault:? ? ? }ifne,ok:=e.(net.Error);ok&&ne.Temporary() {iftempDelay==0{tempDelay=5*time.Millisecond}else{tempDelay*=2}ifmax:=1*time.Second;tempDelay>max{tempDelay=max}srv.logf("http: Accept error: %v; retrying in %v",e,tempDelay)time.Sleep(tempDelay)continue}returne}tempDelay=0c:=srv.newConn(rw)c.setState(c.rwc,StateNew)// before Serve can returngoc.serve(ctx)? }}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末商源,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子谋减,更是在濱河造成了極大的恐慌牡彻,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逃顶,死亡現(xiàn)場離奇詭異讨便,居然都是意外死亡,警方通過查閱死者的電腦和手機以政,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門霸褒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盈蛮,你說我怎么就攤上這事废菱。” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵殊轴,是天一觀的道長衰倦。 經(jīng)常有香客問我,道長旁理,這世上最難降的妖魔是什么樊零? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮孽文,結(jié)果婚禮上驻襟,老公的妹妹穿的比我還像新娘。我一直安慰自己芋哭,他們只是感情好沉衣,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著减牺,像睡著了一般豌习。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拔疚,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天肥隆,我揣著相機與錄音,去河邊找鬼草雕。 笑死巷屿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的墩虹。 我是一名探鬼主播嘱巾,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诫钓!你這毒婦竟也來了旬昭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤菌湃,失蹤者是張志新(化名)和其女友劉穎问拘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惧所,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡骤坐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了下愈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纽绍。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖势似,靈堂內(nèi)的尸體忽然破棺而出拌夏,到底是詐尸還是另有隱情僧著,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布障簿,位于F島的核電站盹愚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏站故。R本人自食惡果不足惜皆怕,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望世蔗。 院中可真熱鬧端逼,春花似錦、人聲如沸污淋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寸爆。三九已至,卻和暖如春盐欺,著一層夾襖步出監(jiān)牢的瞬間赁豆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工冗美, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留魔种,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓粉洼,卻偏偏與公主長得像节预,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子属韧,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容