您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Go語言的技術(shù)特點是什么”,內(nèi)容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“Go語言的技術(shù)特點是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
先來看個例子:
package main import ( "fmt" "time" ) // 要在goroutine中運行的函數(shù)。done通道將被用來通知工作已經(jīng)完成。 func worker(done chan bool) { fmt.Print("working...") time.Sleep(time.Second) fmt.Println("done") // 通知完成。 done <- true } func main() { // 創(chuàng)建一個通道 done := make(chan bool, 1) go worker(done) // 等待done變?yōu)閠rue <-done }
上例中是一個在Go語言中使用goroutine和通道的例子。 其中:
? go 關(guān)鍵字是用來啟動一個goroutine
? done <- true, 向通道傳值
? <-done, 讀取通道值
Go是由RobertGriesemer、RobPike和KenThompson在Google設計的一種靜態(tài)類型化的、須編譯后才能運行的編程語言。
Go在語法上類似于C語言,但它具有C語言沒有的優(yōu)勢,如內(nèi)存安全、垃圾回收、結(jié)構(gòu)化的類型和CSP風格的并發(fā)性。
它的域名是http://golang.org,所以通常被稱為"Golang",但正確的名稱是Go。
Go的設計受C語言的影響,但更加簡單和安全。該語言包括如下特點:
采用動態(tài)語言中比較常見的語法和環(huán)境模式:
可選的簡明變量聲明和通過類型推理進行初始化(如果使用x := 0而不是int x= 0;或var x= 0;)。
快速編譯。
遠程包管理(go get)和在線包文檔。
針對特定問題的獨特方法:
內(nèi)置的并發(fā)基元:輕量級處理機制(goroutines)、通道和select語句。
用接口系統(tǒng)代替虛擬繼承,用類型嵌入代替非虛擬繼承。
默認情況下,由一個工具鏈生成靜態(tài)鏈接的原生二進制文件,沒有外部依賴關(guān)系。
希望保持語言規(guī)范足夠簡單,程序員容易掌握。
Go的語法包含C語言中保持代碼簡潔性和可讀性的語法特點。
引入了一個聯(lián)合聲明/初始化操作符,允許程序員寫出i := 3或s :="Hello, world!",而不需要指定使用的變量類型。
這與C語言中的int i= 3; 和 const char *s = "Hello, world!";形成鮮明對比。
分號仍然是終止語句,但在行結(jié)束時是隱含的。
在Go中,一個函數(shù)方法可以返回多個值,返回一個結(jié)果和錯誤err組合對是向調(diào)用者提示錯誤的常規(guī)方式。
Go的范圍表達式允許在數(shù)組、動態(tài)數(shù)組、字符串、字典和通道上進行簡潔的迭代,在C語言中,有三種循環(huán)來實現(xiàn)這個功能。
Go有許多內(nèi)置的類型,包括數(shù)字類型(byte、int64、float32等)、booleans和字符串(string)。
字符串是不可更改的。
內(nèi)置的運算符和關(guān)鍵字(而不是函數(shù))提供了串聯(lián)、比較和UTF-8編碼/解碼。
記錄類型可以用struct關(guān)鍵字定義。
對于每個類型T和每個非負整數(shù)常數(shù)n,都有一個數(shù)組類型,表示為[n]T,因此,不同長度的數(shù)組有不同的類型。
動態(tài)數(shù)組可以作為"Slice"使用,如對于某類型T,表示為[]T。這些數(shù)組有一個長度和一個容量,容量規(guī)定了何時需要分配新的內(nèi)存來擴展數(shù)組。若干個Slice可以共享它們的底層內(nèi)存。
所有類型都可以定義指針, T類型的指針可定義為*T。地址抽取和隱式訪問使用&和*操作符,這跟C語言一樣,或者隱式的通過方法調(diào)用或?qū)傩栽L問使用。
除了標準庫中的特殊的unsafe.Pointer類型,一般指針沒有指針運算。
對于一個組合對類型K、V,類型map[K]V是將類型K鍵映射到類型V值的哈希表的類型。
chan T是一個通道,允許在并發(fā)的Go進程之間發(fā)送T類型的值。
除了對接口的支持外,Go的類型系統(tǒng)是顯示的:類型關(guān)鍵字可以用來定義一個新的命名類型,它與其他具有相同布局的命名類型(對于結(jié)構(gòu)體來說,相同的成員按相同的順序排列)不同。類型之間的一些轉(zhuǎn)換(如各種整數(shù)類型之間的轉(zhuǎn)換)是預先定義好的,添加一個新的類型可以定義額外的轉(zhuǎn)換,但命名類型之間的轉(zhuǎn)換必須始終顯式調(diào)用。例如,類型關(guān)鍵字可以用來定義IPv4地址的類型,基于32位無符號整數(shù):
type ipv4addr uint32
通過這個類型定義,ipv4addr(x)將uint32值x解釋為IP地址。如果簡單地將x分配給類型為ipv4addr的變量將會是一個類型錯誤。
常量表達式既可以是類型化的,也可以是 "非類型化的";如果它們所代表的值通過了編譯時的檢查,那么當它們被分配給一個類型化的變量時,就會被賦予一個類型。
函數(shù)類型由func關(guān)鍵字表示;它們?nèi)?個或更多的參數(shù)并返回0個或更多的值,這些值都是要聲明類型的。
參數(shù)和返回值決定了一個函數(shù)的類型;比如,func(string, int32)(int, error)就是輸入一個字符串和一個32位有符號的整數(shù),并返回一個有符號的整數(shù)和一個錯誤(內(nèi)置接口類型)的值的函數(shù)類型。
任何命名的類型都有一個與之相關(guān)聯(lián)的方法集合。上面的IP地址例子可以用一個檢查其值是否為已知標準的方法來擴展:
// ZeroBroadcast報告addr是否為255.255.255.255.255。 func (addr ipv4addr) ZeroBroadcast() bool { return addr == 0xFFFFFFFF }
以上的函數(shù)在ipv4addr上增加了一個方法,但這個方法在uint32上沒有。
Go提供了兩個功能來取代類繼承。
首先是嵌入方法,可以看成是一種自動化的構(gòu)成形式或委托代理。
第二種是接口,它提供了運行時的多態(tài)性。
接口是一類型,它在Go的類型系統(tǒng)中提供了一種有限的結(jié)構(gòu)類型化形式。
一個接口類型的對象同時也有另一種類型的定義對應,這點就像C++對象同時具有基類和派生類的特征一樣。
Go接口是在Smalltalk編程語言的協(xié)議基礎上設計的。
在描述Go接口時使用了鴨式填充這個術(shù)語。
雖然鴨式填充這個術(shù)語沒有精確的定義,它通常是說這些對象的類型一致性沒有被靜態(tài)檢查。
由于Go接口的一致性是由Go編譯器靜態(tài)地檢查的,所以Go的作者們更喜歡使用結(jié)構(gòu)類型化這個詞。
接口類型的定義按名稱和類型列出了所需的方法。任何存在與接口類型I的所需方法匹配的函數(shù)的T類型的對象也是類型I的對象。類型T的定義不需要也不能識別類型I。例如,如果Shape、Square和Circle被定義為:
import "math" type Shape interface { Area() float64 } type Square struct { // 注:沒有 "實現(xiàn) "聲明 side float64 } func (sq Square) Area() float64 { return sq.side * sq.side } type Circle struct { // 這里也沒有 "實現(xiàn) "聲明 radius float64 } func (c Circle) Area() float64 { return math.Pi * math.Pow(c.radius, 2) }
一個正方形和一個圓都隱含著一個形狀(Shape)類型,并且可以被分配給一個形狀(Shape)類型的變量。
Go的接口系統(tǒng)使用了了結(jié)構(gòu)類型。接口也可以嵌入其他接口,其效果是創(chuàng)建一個組合接口,而這個組合接口正是由實現(xiàn)嵌入接口的類型和新定義的接口所增加的方法來滿足的。
Go標準庫在多個地方使用接口來提供通用性,這包括基于Reader和Writer概念的輸入輸出系統(tǒng)。
除了通過接口調(diào)用方法,Go還允許通過運行時類型檢查將接口值轉(zhuǎn)換為其他類型。這就是類型斷言和類型切換。
空接口{}是一個重要的基本情況,因為它可以引用任何類型的選項。它類似于Java或C#中的Object類,可以滿足任何類型,包括像int這樣的內(nèi)置類型。
使用空接口的代碼不能簡單地在被引用的對象上調(diào)用方法或內(nèi)置操作符,但它可以存儲interface{}值,通過類型斷言或類型切換嘗試將其轉(zhuǎn)換為更有用的類型,或者用Go的reflect包來檢查它。
因為 interface{} 可以引用任何值,所以它是一種擺脫靜態(tài)類型化限制的有效方式,就像C 語言中的 void*,但在運行時會有額外的類型檢查。
接口值是使用指向數(shù)據(jù)的指針和第二個指向運行時類型信息的指針來實現(xiàn)的。與Go中其他一些使用指針實現(xiàn)的類型一樣,如果未初始化,接口值是零。
在Go的包系統(tǒng)中,每個包都有一個路徑(如"compress/bzip2 "或"http://golang.org/x/net/html")和一個名稱(如bzip2或html)。
對其他包的定義的引用必須始終以其他包的名稱作為前綴,并且只有其他包的大寫的名稱才能被訪問:io.Reader是公開的,但bzip2.reader不是。
go get命令可以檢索存儲在遠程資源庫中的包,鼓勵開發(fā)者在開發(fā)包時,在與源資源庫相對應的基礎路徑
內(nèi)開發(fā)程序包,從而減少將來在標準庫或其他外部庫中名稱碰撞的可能性。
有人提議Go引入一個合適的包管理解決方案,類似于CPANfor Perl或Rust的Cargo系統(tǒng)或Node的npm系統(tǒng)。
在計算機科學中,通信順序過程(communicating sequential processes,CSP)是一種描述并發(fā)系統(tǒng)中交互模式的正式語言,它是并發(fā)數(shù)學理論家族中的一個成員,被稱為過程算法(process algebras),或者說過程計算(process calculate),是基于消息的通道傳遞的數(shù)學理論。
CSP在設計Oceam編程語言時起了很大的影響,同時也影響了Limbo、RaftLib、Go、Crystal和Clojure的core.async等編程語言的設計。
CSP最早是由TonyHoare在1978年的一篇論文中描述的,后來有了很大的發(fā)展。
CSP作為一種工具被實際應用于工業(yè)上,用于指定和驗證各種不同系統(tǒng)的并發(fā)功能,如T9000Transputer以及安全的電子商務系統(tǒng)。
CSP本身的理論目前也仍然是被積極研究的對象,包括增加其實際適用范圍的工作,如增加可分析的系統(tǒng)規(guī)模。
Go語言有內(nèi)置的機制和庫支持來編寫并發(fā)程序。并發(fā)不僅指的是CPU的并行性,還指的是異步性處理:讓相對慢的操作,如數(shù)據(jù)庫或網(wǎng)絡讀取等操作在做其他工作的同時運行,這在基于事件的服務器中很常見。
主要的并發(fā)構(gòu)造是goroutine,這是一種輕量級處理類型。一個以go關(guān)鍵字為前綴的函數(shù)調(diào)用會在一個新的goroutine中啟動這個函數(shù)。
語言規(guī)范并沒有指定如何實現(xiàn)goroutine,但目前的實現(xiàn)將Go進程的goroutine復用到一個較小的操作系統(tǒng)線程集上,類似于Erlang中的調(diào)度。
雖然一個標準的庫包具有大多數(shù)經(jīng)典的并發(fā)控制結(jié)構(gòu)(mutex鎖等),但Go并發(fā)程序更偏重于通道,它提供了goroutines之間的消息傳功能。
可選的緩沖區(qū)以FIFO順序存儲消息,允許發(fā)送的goroutines在收到消息之前繼續(xù)進行。
通道是類型化的,所以chan T類型的通道只能用于傳輸T類型的消息。
特殊語法約定用于對它們進行操作;<-ch是一個表達式,它使執(zhí)行中的goroutine在通道ch上阻塞,直到有一個值進來,而ch<- x則是發(fā)送值x(可能阻塞直到另一個goroutine接收到這個值)。
內(nèi)置的類似于開關(guān)的選擇語句可以用來實現(xiàn)多通道上的非阻塞通信。Go有一個內(nèi)存模型,描述了goroutine必須如何使用通道或其他操作來安全地共享數(shù)據(jù)。
通道的存在使Go有別于像Erlang這樣的actor模型式的并發(fā)語言,在這種語言中,消息是直接面向actor(對應于goroutine)的。在Go中,可以通過在goroutine和通道之間保持一對一的對應關(guān)系來,Go語言也允許多個goroutine共享一個通道,或者一個goroutine在多個通道上發(fā)送和接收消息。
通過這些功能,人們可以構(gòu)建像workerpools、流水線(比如說,在下載文件時,對文件進行解壓縮和解析)、帶超時的后臺調(diào)用、對一組服務的"扇出"并行調(diào)用等并發(fā)構(gòu)造。
通道也有一些超越進程間通信的常規(guī)概念的用途,比如作為一個并發(fā)安全的回收緩沖區(qū)列表,實現(xiàn)coroutines和實現(xiàn)迭代器。
Go的并發(fā)相關(guān)的結(jié)構(gòu)約定(通道和替代通道輸入)來自于TonyHoare的通信順序進程模型。
不像以前的并發(fā)編程語言,如Occam或Limbo(Go的共同設計者RobPike曾在此基礎上工作過的語言),Go沒有提供任何內(nèi)置的安全或可驗證的并發(fā)概念。
雖然在Go中,上述的通信處理模型是推薦使用的,但不是唯一的:一個程序中的所有g(shù)oroutines共享一個單一的地址空間。這意味著可突變對象和指針可以在goroutines之間共享。
有一項研究比較了一個不熟悉Go語言的老練程序員編寫的程序的大?。ㄒ源a行數(shù)為單位)和速度,以及一個Go專家(來自Google開發(fā)團隊)對這些程序的修正,對Chapel、Cilk和IntelTBB做了同樣的研究。
研究發(fā)現(xiàn),非專家傾向于用每個遞歸中的一條Go語句來寫分解-解決算法,而專家則用每個處理器的一條Go語句來寫分布式工作同步程序。Go專家的程序通常更快,但也更長。
Goroutine對于如何訪問共享數(shù)據(jù)沒有限制,這使得條件競賽成為可能的問題。
具體來說,除非程序通過通道或其他方式顯式同步,否則多個goroutine共享讀寫一個內(nèi)存區(qū)域可能會發(fā)生問題。
此外,Go的內(nèi)部數(shù)據(jù)結(jié)構(gòu),如接口值、動態(tài)數(shù)組頭、哈希表和字符串頭等內(nèi)部數(shù)據(jù)結(jié)構(gòu)也不能幸免于條件競賽,因此在多線程程序中,如果修改這些類型的共享實例沒有同步,就會存在影響類型和內(nèi)存安全的情況。
gc工具鏈中的鏈接器默認會創(chuàng)建靜態(tài)鏈接的二進制文件,因此所有的Go二進制文件都包括Go運行所需要的內(nèi)容。
Go故意省略了其他語言中常見的一些功能,包括繼承、通用編程、斷言、指針運算、隱式類型轉(zhuǎn)換、無標記的聯(lián)合和標記聯(lián)合。
Go作者在Go程序的風格方面付出了大量的努力:
gofmt工具自動規(guī)范了代碼的縮進、間距和其他表面級的細節(jié)。
與Go一起分發(fā)的工具和庫推薦了一些標準的方法,比如API文檔(godoc)、 測試(go test)、構(gòu)建(go build)、包管理(go get)等等。
Go的一些規(guī)則跟其他語言不同,例如禁止循環(huán)依賴、未使用的變量或?qū)?、隱式類型轉(zhuǎn)換等。
某些特性的省略(例如,函數(shù)編程的一些捷徑,如map和Java風格的try/finally塊)編程風格顯式化,具體化,簡單化。
Go團隊從第一天開始就發(fā)布了一個Go的語法使用集合,后來還收集了一些代碼的評論,講座和官方博客文章,來推廣Go的風格和編碼理念。
主要的Go發(fā)行版包括構(gòu)建、測試和分析代碼的工具。
? go build,它只使用源文件中的信息來構(gòu)建Go二進制文件,不使用單獨的makefiles。
? gotest,用于單元測試和微基準
? go fmt,用于格式化代碼
? go get,用于檢索和安裝遠程包。
? go vet,靜態(tài)分析器,查找代碼中的潛在錯誤。
? go run,構(gòu)建和執(zhí)行代碼的快捷方式
? godoc,用于顯示文檔或通過HTTP
? gorename,用于以類型安全的方式重命名變量、函數(shù)等。
? go generate,一個標準的調(diào)用代碼生成器的方法。
它還包括分析和調(diào)試支持、運行時診斷(例如,跟蹤垃圾收集暫停)和條件競賽測試器。
第三方工具的生態(tài)系統(tǒng)增強了標準的發(fā)布系統(tǒng),如:
gocode,它可以在許多文本編輯器中自動完成代碼,
goimports(由Go團隊成員提供),它可以根據(jù)需要自動添加/刪除包導入,以及errcheck,它可以檢測可能無意中被忽略的錯誤代碼。
流行的Go代碼工具:
? GoLand:JetBrains公司的IDE。
? VisualStudio Code
? LiteIDE:一個"簡單、開源、跨平臺的GoIDE"
? Vim:用戶可以安裝插件:
? vim-go
用Go編寫的一些著名的開源應用包括:
? Caddy,一個開源的HTTP/2web服務器,具有自動HTTPS功能。
? CockroachDB,一個開源的、可生存的、強一致性、可擴展的SQL數(shù)據(jù)庫。
? Docker,一套用于部署Linux容器的工具。
? Ethereum,以太幣虛擬機區(qū)塊鏈的Go-Ethereum實現(xiàn)。
? Hugo,一個靜態(tài)網(wǎng)站生成器
? InfluxDB,一個專門用于處理高可用性和高性能要求的時間序列數(shù)據(jù)的開源數(shù)據(jù)庫。
? InterPlanetaryFile System,一個可內(nèi)容尋址、點對點的超媒體協(xié)議。
? Juju,由UbuntuLinux的包裝商Canonical公司推出的服務協(xié)調(diào)工具。
? Kubernetes容器管理系統(tǒng)
? lnd,比特幣閃電網(wǎng)絡的實現(xiàn)。
? Mattermost,一個團隊聊天系統(tǒng)
? NATSMessaging,是一個開源的消息傳遞系統(tǒng),其核心設計原則是性能、可擴展性和易用性。
? OpenShift,云計算服務平臺
? Snappy,一個由Canonical開發(fā)的UbuntuTouch軟件包管理器。
? Syncthing,一個開源的文件同步客戶端/服務器應用程序。
? Terraform,是HashiCorp公司的一款開源的多云基礎設施配置工具。
其他使用Go的知名公司和網(wǎng)站包括:
? Cacoo,使用Go和gRPC渲染用戶儀表板頁面和微服務。
? Chango,程序化廣告公司,在其實時競價系統(tǒng)中使用Go。
? CloudFoundry,平臺即服務系統(tǒng)
? Cloudflare,三角編碼代理Railgun,分布式DNS服務,以及密碼學、日志、流處理和訪問SPDY網(wǎng)站的工具。
? 容器Linux(原CoreOS),是一個基于Linux的操作系統(tǒng),使用Docker容器和rkt容器。
? Couchbase、Couchbase服務器內(nèi)的查詢和索引服務。
? Dropbox,將部分關(guān)鍵組件從Python遷移到了Go。
? 谷歌,許多項目,特別是下載服務器http://dl.google.com。
? Heroku,Doozer,一個提供鎖具服務的公司
? HyperledgerFabric,一個開源的企業(yè)級分布式分類賬項目。
? MongoDB,管理MongoDB實例的工具。
? Netflix的服務器架構(gòu)的兩個部分。
? Nutanix,用于其企業(yè)云操作系統(tǒng)中的各種微服務。
? Plug.dj,一個互動式在線社交音樂流媒體網(wǎng)站。
? SendGrid是一家位于科羅拉多州博爾德市的事務性電子郵件發(fā)送和管理服務。
? SoundCloud,"幾十個系統(tǒng)"
? Splice,其在線音樂協(xié)作平臺的整個后端(API和解析器)。
? ThoughtWorks,持續(xù)傳遞和即時信息的工具和應用(CoyIM)。
? Twitch,他們基于IRC的聊天系統(tǒng)(從Python移植過來的)。
? Uber,處理大量基于地理信息的查詢。
package main import "fmt" func main() { fmt.Println("Hello, world!") }
package main import ( "fmt" "time" ) func readword(ch chan string) { fmt.Println("Type a word, then hit Enter.") var word string fmt.Scanf("%s", &word) ch <- word } func timeout(t chan bool) { time.Sleep(5 * time.Second) t <- false } func main() { t := make(chan bool) go timeout(t) ch := make(chan string) go readword(ch) select { case word := <-ch: fmt.Println("Received", word) case <-t: fmt.Println("Timeout.") } }
沒有測試的代碼是不完整的,因此我們需要看看代碼測試部分的編寫。
代碼:
func ExtractUsername(email string) string { at := strings.Index(email, "@") return email[:at] }
測試案例:
func TestExtractUsername(t *testing.T) { type args struct { email string } tests := []struct { name string args args want string }{ {"withoutDot", args{email: "r@google.com"}, "r"}, {"withDot", args{email: "jonh.smith@example.com"}, "jonh.smith"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := ExtractUsername(tt.args.email); got != tt.want { t.Errorf("ExtractUsername() = %v, want %v", got, tt.want) } }) } }
接下來我寫一個例子創(chuàng)建REST API后端服務:
我們的服務提供如下的API:
### GET http://localhost:10000/ ### GET http://localhost:10000/all ### GET http://localhost:10000/article/1 ### POST http://localhost:10000/article HTTP/1.1 { "Id": "3", "Title": "Hello 2", "desc": "Article Description", "content": "Article Content" } ### PUT http://localhost:10000/article HTTP/1.1 { "Id": "2", "Title": "Hello 2 Update", "desc": "Article Description Update", "content": "Article Content Update" }
完整代碼:
package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "github.com/gorilla/mux" ) type Article struct { Id string `json:"Id"` Title string `json:"Title"` Desc string `json:"desc"` Content string `json:"content"` } var MapArticles map[string]Article var Articles []Article func returnAllArticles(w http.ResponseWriter, r *http.Request) { fmt.Println("Endpoint Hit: returnAllArticles") json.NewEncoder(w).Encode(Articles) } func homePage(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Welcome to the HomePage!") fmt.Println("Endpoint Hit: homePage") } func createNewArticle(w http.ResponseWriter, r *http.Request) { reqBody, _ := ioutil.ReadAll(r.Body) var article Article json.Unmarshal(reqBody, &article) Articles = append(Articles, article) MapArticles[article.Id] = article json.NewEncoder(w).Encode(article) } func updateArticle(w http.ResponseWriter, r *http.Request) { reqBody, _ := ioutil.ReadAll(r.Body) var article Article json.Unmarshal(reqBody, &article) found := false for index, v := range Articles { if v.Id == article.Id { // Found! found = true Articles[index] = article } } if !found { Articles = append(Articles, article) } MapArticles[article.Id] = article json.NewEncoder(w).Encode(article) } func returnSingleArticle(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) key := vars["id"] fmt.Fprintf(w, "Key: %s \n", key) json.NewEncoder(w).Encode(MapArticles[key]) } func handleRequests() { myRouter := mux.NewRouter().StrictSlash(true) myRouter.HandleFunc("/", homePage) myRouter.HandleFunc("/all", returnAllArticles) myRouter.HandleFunc("/article", createNewArticle).Methods("POST") myRouter.HandleFunc("/article", updateArticle).Methods("PUT") myRouter.HandleFunc("/article/{id}", returnSingleArticle) log.Fatal(http.ListenAndServe(":10000", myRouter)) } func main() { fmt.Println("Rest API is ready ...") MapArticles = make(map[string]Article) Articles = []Article{ Article{Id: "1", Title: "Hello", Desc: "Article Description", Content: "Article Content"}, Article{Id: "2", Title: "Hello 2", Desc: "Article Description", Content: "Article Content"}, } for _, a := range Articles { MapArticles[a.Id] = a } handleRequests() }
調(diào)用添加,更新API以后返回所有數(shù)據(jù)的測試結(jié)果:
讀到這里,這篇“Go語言的技術(shù)特點是什么”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。