Go語(yǔ)言也稱(chēng) Golang,兼具效率、性能、安全、健壯等特性。這套Go語(yǔ)言教程(Golang教程)通俗易懂,深入淺出,既適合沒(méi)有基礎(chǔ)的讀者快速入門(mén),也適合工作多年的程序員查閱知識(shí)點(diǎn)。
我們提供的服務(wù)有:網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、阿爾山ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢(xún)和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的阿爾山網(wǎng)站制作公司
Go 語(yǔ)言
這套教程在講解一些知識(shí)點(diǎn)時(shí),將 Go 語(yǔ)言和其他多種語(yǔ)言進(jìn)行對(duì)比,讓掌握其它編程語(yǔ)言的讀者能迅速理解 Go 語(yǔ)言的特性。Go語(yǔ)言從底層原生支持并發(fā),無(wú)須第三方庫(kù)、開(kāi)發(fā)者的編程技巧和開(kāi)發(fā)經(jīng)驗(yàn)就可以輕松搞定。
Go語(yǔ)言(或 Golang)起源于 2007 年,并在 2009 年正式對(duì)外發(fā)布。Go 是非常年輕的一門(mén)語(yǔ)言,它的主要目標(biāo)是“兼具 Python 等動(dòng)態(tài)語(yǔ)言的開(kāi)發(fā)速度和 C/C++ 等編譯型語(yǔ)言的性能與安全性”。
Go語(yǔ)言是編程語(yǔ)言設(shè)計(jì)的又一次嘗試,是對(duì)類(lèi)C語(yǔ)言的重大改進(jìn),它不但能讓你訪問(wèn)底層操作系統(tǒng),還提供了強(qiáng)大的網(wǎng)絡(luò)編程和并發(fā)編程支持。Go語(yǔ)言的用途眾多,可以進(jìn)行網(wǎng)絡(luò)編程、系統(tǒng)編程、并發(fā)編程、分布式編程。
Go語(yǔ)言的推出,旨在不損失應(yīng)用程序性能的情況下降低代碼的復(fù)雜性,具有“部署簡(jiǎn)單、并發(fā)性好、語(yǔ)言設(shè)計(jì)良好、執(zhí)行性能好”等優(yōu)勢(shì),目前國(guó)內(nèi)諸多 IT 公司均已采用Go語(yǔ)言開(kāi)發(fā)項(xiàng)目。Go語(yǔ)言有時(shí)候被描述為“C 類(lèi)似語(yǔ)言”,或者是“21 世紀(jì)的C語(yǔ)言”。Go 從C語(yǔ)言繼承了相似的表達(dá)式語(yǔ)法、控制流結(jié)構(gòu)、基礎(chǔ)數(shù)據(jù)類(lèi)型、調(diào)用參數(shù)傳值、指針等很多思想,還有C語(yǔ)言一直所看中的編譯后機(jī)器碼的運(yùn)行效率以及和現(xiàn)有操作系統(tǒng)的無(wú)縫適配。
因?yàn)镚o語(yǔ)言沒(méi)有類(lèi)和繼承的概念,所以它和 Java 或 C++ 看起來(lái)并不相同。但是它通過(guò)接口(interface)的概念來(lái)實(shí)現(xiàn)多態(tài)性。Go語(yǔ)言有一個(gè)清晰易懂的輕量級(jí)類(lèi)型系統(tǒng),在類(lèi)型之間也沒(méi)有層級(jí)之說(shuō)。因此可以說(shuō)Go語(yǔ)言是一門(mén)混合型的語(yǔ)言。
此外,很多重要的開(kāi)源項(xiàng)目都是使用Go語(yǔ)言開(kāi)發(fā)的,其中包括 Docker、Go-Ethereum、Thrraform 和 Kubernetes。Go 是編譯型語(yǔ)言,Go 使用編譯器來(lái)編譯代碼。編譯器將源代碼編譯成二進(jìn)制(或字節(jié)碼)格式;在編譯代碼時(shí),編譯器檢查錯(cuò)誤、優(yōu)化性能并輸出可在不同平臺(tái)上運(yùn)行的二進(jìn)制文件。要?jiǎng)?chuàng)建并運(yùn)行 Go 程序,程序員必須執(zhí)行如下步驟。
使用文本編輯器創(chuàng)建 Go 程序;
保存文件;編譯程序;運(yùn)行編譯得到的可執(zhí)行文件。
這不同于 Python、Ruby 和 JavaScript 等語(yǔ)言,它們不包含編譯步驟。Go 自帶了編譯器,因此無(wú)須單獨(dú)安裝編譯器。
鏈喬教育在線旗下學(xué)碩創(chuàng)新區(qū)塊鏈技術(shù)工作站是中國(guó)教育部學(xué)校規(guī)劃建設(shè)發(fā)展中心開(kāi)展的“智慧學(xué)習(xí)工場(chǎng)2020-學(xué)碩創(chuàng)新工作站 ”唯一獲準(zhǔn)的“區(qū)塊鏈技術(shù)專(zhuān)業(yè)”試點(diǎn)工作站。專(zhuān)業(yè)站立足為學(xué)生提供多樣化成長(zhǎng)路徑,推進(jìn)專(zhuān)業(yè)學(xué)位研究生產(chǎn)學(xué)研結(jié)合培養(yǎng)模式改革,構(gòu)建應(yīng)用型、復(fù)合型人才培養(yǎng)體系。
包 utf-8 實(shí)現(xiàn)的功能和常量用于文章utf8編碼,包含runes和utf8字節(jié)序列的轉(zhuǎn)換功能.在unicode中,一個(gè)中文占兩個(gè)字節(jié),utf-8中一個(gè)中文占三個(gè)字節(jié),golang默認(rèn)的編碼是utf-8編碼,因此默認(rèn)一個(gè)中文占三個(gè)字節(jié),但是golang中的字符串底層實(shí)際上是一個(gè)byte數(shù)組.
Output:
RuneSelf該值的字節(jié)碼值為128,在判斷是否是常規(guī)的ascii碼是使用。hicb字節(jié)碼值為191. FF 的對(duì)應(yīng)的字節(jié)碼為255。
計(jì)算字符串中的rune數(shù)量,原理:首先取出字符串的碼值,然后判斷是不是個(gè)小于128的,如果是小于則直接continue.rune個(gè)數(shù)++.
如果是個(gè)十六進(jìn)制f1.的則是無(wú)效字符,直接continue.rune個(gè)數(shù)++,也就是說(shuō)一個(gè)無(wú)效的字符也當(dāng)成一個(gè)字長(zhǎng)為1的rune.如果字符的碼值在first列表中的值和7按位的結(jié)果為其字長(zhǎng),比如上面示例中的 鋼 。其字長(zhǎng)為三位,第一位的值為 233 .二進(jìn)制形式為 11101001 ;與7按位與后的值為0.從acceptRanges中取出的結(jié)果為{locb, hicb}。也就是標(biāo)識(shí) ox80 到 0xbf 之間的值。而結(jié)果n也就是直接size+3跳過(guò)3個(gè)字節(jié)后,rune個(gè)數(shù)++。其他函數(shù)的處理流程差不多,不再過(guò)多敘述。
示例:
ValidString返回值表明參數(shù)字符串是否是一個(gè)合法的可utf8編碼的字符串。
RuneCount返回參數(shù)中包含的rune數(shù)量,第一個(gè)例子中將 utf8.RuneCountInString ,改成該方法調(diào)用,返回的結(jié)果相同。錯(cuò)誤的和短的被當(dāng)成一個(gè)長(zhǎng)一字節(jié)的rune.單個(gè)字符 H 就表示一個(gè)長(zhǎng)度為1字節(jié)的rune.
該函數(shù)標(biāo)識(shí)參數(shù)是否以一個(gè)可編碼的rune開(kāi)頭,上面的例子中,因?yàn)樽址且砸粋€(gè)ascii碼值在0-127內(nèi)的字符開(kāi)頭,所以在執(zhí)行
first[p[0]] 時(shí),取到的是 p[0] 是72,在first列表中,127之前的值都相同都為 0xF0 ,十進(jìn)制標(biāo)識(shí)為240,與7按位與后值為0,所以,直接返回 true .
和FullRune類(lèi)似,只是參數(shù)為字符串形式
Go中的binary包實(shí)現(xiàn)了簡(jiǎn)單的數(shù)字與字節(jié)序列的轉(zhuǎn)換以及變長(zhǎng)值的編解碼
package main
import ( "fmt" "bytes" "encoding/binary" ) func main(){ n := 0x12345678 bytesBuffer := bytes.NewBuffer([]byte{}) //BigEndian 大端順序存儲(chǔ) LittleEndian小端順序存儲(chǔ) binary.Write(bytesBuffer, binary.BigEndian, int32(n)) data:=bytesBuffer.Bytes() fmt.Printf("[0]: %#x addr:%#x\n",data[0],data[0]) fmt.Printf("[0]: %#x addr:%#x\n",data[1],data[1]) fmt.Printf("[0]: %#x addr:%#x\n",data[2],data[2]) fmt.Printf("[0]: %#x addr:%#x\n",data[3],data[3]) }
輸出
[0]: 0x12 addr:0xc042010248 [1]: 0x34 addr:0xc042010249 [2]: 0x56 addr:0xc04201024a [3]: 0x78 addr:0xc04201024b
也可以使用下面的方式
n := 0x12345678 var data []byte = make([]byte,4) //操作的都是無(wú)符號(hào)整型 binary.BigEndian.PutUint32(data,uint32(n))
可以使用下面的方式判斷當(dāng)前系統(tǒng)的字節(jié)序類(lèi)型
const INT_SIZE int = int(unsafe.Sizeof(0))
//判斷我們系統(tǒng)中的字節(jié)序類(lèi)型 func systemEdian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(i)) if bs[0] == 0 { fmt.Println("system edian is little endian") } else { fmt.Println("system edian is big endian") } }
先配置Header最長(zhǎng)讀取時(shí)間、req最長(zhǎng)讀取時(shí)間、req最大讀取長(zhǎng)度默認(rèn)6M。
RFC7230禁止\r\n參數(shù),Url中只允許包含英文字母(a-zA-Z)、數(shù)字(0-9)、-_.~4個(gè)特殊字符以及所有保留字符。但go net/http包放寬了這個(gè)要求。
先構(gòu)建newTextprotoReader,由于緩沖區(qū)是對(duì)象復(fù)用的,用完后要defer put。共完以以下解析任務(wù):
TextprotoReader數(shù)據(jù)結(jié)構(gòu),將字節(jié)碼Reader轉(zhuǎn)成文本Reader。
第一步,從第一行解析出method uri prototype。
第二步解析URL。url.URL數(shù)據(jù)結(jié)構(gòu):
解析Scheme,協(xié)議前綴(小寫(xiě))。有查詢(xún)參數(shù)?,則配置url.ForceQuery url.RawQuery。有認(rèn)證信息///...//,則解析url.User url.Host。最后配置url.Path和url.RawPath,如果Path==RawPath,則RawPath=""。
第三步解析MIMEHeader。
第四步readTransfer。重新配置如下參數(shù):RequestMethod ProtoMajor ProtoMinor Header Trailer ContentLength Close。對(duì)于Body,如果encodings支持chunked,讀取流用chunkedReader包裹。默認(rèn)情況用LimitedReader,無(wú)body賦空的struct{}。
以下情況返回非空err,示得到正確的請(qǐng)求:
最后配置req.ctx req.RemoteAddr req.TLS body.doEarlyClose = true。
構(gòu)建Response:
其中closeNotifyCh必須在構(gòu)建時(shí)初始化,沒(méi)有content所以先置contentLength為-1。
配置w.cw并被w.w包裹。w.cw緩沖默認(rèn)大小2M。
獲取Request可能出現(xiàn)如下錯(cuò)誤:
先上響應(yīng)數(shù)據(jù)結(jié)構(gòu):
response字段可以分類(lèi)為:大對(duì)象、緩沖、KV對(duì)或bool型的狀態(tài)參數(shù)。
大對(duì)象有:
狀態(tài)字段:
chunkWriter數(shù)據(jù)結(jié)構(gòu):
chunkWriter包裹了Response,功能之一是完成Header設(shè)置,包括Content-Type Content-Length chunk-header。bufio.Writer是chunkWriter是緩沖包裹。
handler將響應(yīng)寫(xiě)入到response.w。
調(diào)用w.w.Flush()將w寫(xiě)入到cw,注意到Flush()操作,如果未刷空緩存并報(bào)錯(cuò),觸發(fā)拷貝操作。報(bào)錯(cuò)不會(huì)退回已寫(xiě)出的數(shù)據(jù)。
進(jìn)而調(diào)用cw.Write(),根據(jù)cw.chunking參數(shù)。
putBufioWriter(w.w)清空resp.w緩沖,如果池化放回sync.pool。
根據(jù)chunkWriter的定義,w.cw.close()負(fù)責(zé)cw的結(jié)束工作:寫(xiě)入換行符和resp.trailers數(shù)據(jù)。
最后刷新TCP緩沖w.conn.bufw.Flush(),完成響應(yīng)包發(fā)送。并正確關(guān)閉request。