主頁 > 資料庫 > 關于GO語言,這篇文章講的很明白

關于GO語言,這篇文章講的很明白

2020-10-15 15:35:44 資料庫

摘要:本文從Go的語法,型別系統,編碼風格,語言工具,編碼工具和使用案例等幾方面對Go語言進行了學習和探討,

Go語言發布之后,很多公司特別是云廠商也開始用Go語言重構產品的基礎架構,而且很多企業都是直接采用Go語言進行開發,最近熱火朝天的Docker就是采用Go語言進行開發的,本文我們一起來探討和學習一下Go語言的技術特點,先來看個例子:

package main
 
import (
    "fmt"
    "time"
)
 
// 要在goroutine中運行的函式,done通道將被用來通知作業已經完成,
func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")
    // 通知完成,
    done <- true
}
 
func main() {
 
    // 創建一個通道
    done := make(chan bool, 1)
    go worker(done)
 
    // 等待done變為true
    <-done
}

上例中是一個在Go語言中使用goroutine和通道的例子, 其中:

? go 關鍵字是用來啟動一個goroutine

? done <- true, 向通道傳值

? <-done, 讀取通道值

一、【概述】

Go是由RobertGriesemer、RobPike和KenThompson在Google設計的一種靜態型別化的、須編譯后才能運行的編程語言,

Go在語法上類似于C語言,但它具有C語言沒有的優勢,如記憶體安全、垃圾回收、結構化的型別和CSP風格的并發性,

它的域名是http://golang.org,所以通常被稱為"Golang",但正確的名稱是Go,

二、【GO的設計思想】

Go的設計受C語言的影響,但更加簡單和安全,該語言包括如下特點:

  • 采用動態語言中比較常見的語法和環境模式:
  • 可選的簡明變數宣告和通過型別推理進行初始化(如果使用x := 0而不是int x= 0;或var x= 0;),
  • 快速編譯,
  • 遠程包管理(go get)和在線包檔案,
  • 針對特定問題的獨特方法:
  • 內置的并發基元:輕量級處理機制(goroutines)、通道和select陳述句,
  • 用介面系統代替虛擬繼承,用型別嵌入代替非虛擬繼承,
  • 默認情況下,由一個工具鏈生成靜態鏈接的原生二進制檔案,沒有外部依賴關系,
  • 希望保持語言規范足夠簡單,程式員容易掌握,

2.1 簡潔的語法

Go的語法包含C語言中保持代碼簡潔性和可讀性的語法特點,

2.1.1 變數宣告

引入了一個聯合宣告/初始化運算子,允許程式員寫出i := 3或s :="Hello, world!",而不需要指定使用的變數型別,

這與C語言中的int i= 3; 和 const char *s = "Hello, world!";形成鮮明對比,

2.1.2 分號隱含

分號仍然是終止陳述句,但在行結束時是隱含的,

2.1.3 回傳多值

在Go中,一個函式方法可以回傳多個值,回傳一個結果和錯誤err組合對是向呼叫者提示錯誤的常規方式,

2.1.4 范圍運算式

Go的范圍運算式允許在陣列、動態陣列、字串、字典和通道上進行簡潔的迭代,在C語言中,有三種回圈來實作這個功能,

2.2 型別系統

2.2.1 內置的型別

Go有許多內置的型別,包括數字型別(byte、int64、float32等)、booleans和字串(string),

字串是不可更改的,

內置的運算子和關鍵字(而不是函式)提供了串聯、比較和UTF-8編碼/解碼,

2.2.2 結構型別

記錄型別可以用struct關鍵字定義,

2.2.3 陣列型別

對于每個型別T和每個非負整數常數n,都有一個陣列型別,表示為[n]T,因此,不同長度的陣列有不同的型別,

動態陣列可以作為"Slice"使用,如對于某型別T,表示為[]T,這些陣列有一個長度和一個容量,容量規定了何時需要分配新的記憶體來擴展陣列,若干個Slice可以共享它們的底層記憶體,

2.2.4 指標

所有型別都可以定義指標, T型別的指標可定義為*T,地址抽取和隱式訪問使用&和*運算子,這跟C語言一樣,或者隱式的通過方法呼叫或屬性訪問使用,

除了標準庫中的特殊的unsafe.Pointer型別,一般指標沒有指標運算,

2.2.5 映射型別

對于一個組合對型別K、V,型別map[K]V是將型別K鍵映射到型別V值的哈希表的型別,

2.2.6 通道型別

chan T是一個通道,允許在并發的Go行程之間發送T型別的值,

2.2.7 顯式型別

除了對介面的支持外,Go的型別系統是顯示的:型別關鍵字可以用來定義一個新的命名型別,它與其他具有相同布局的命名型別(對于結構體來說,相同的成員按相同的順序排列)不同,型別之間的一些轉換(如各種整數型別之間的轉換)是預先定義好的,添加一個新的型別可以定義額外的轉換,但命名型別之間的轉換必須始終顯式呼叫,例如,型別關鍵字可以用來定義IPv4地址的型別,基于32位無符號整數:

type ipv4addr uint32

通過這個型別定義,ipv4addr(x)將uint32值x解釋為IP地址,如果簡單地將x分配給型別為ipv4addr的變數將會是一個型別錯誤,

常量運算式既可以是型別化的,也可以是 "非型別化的";如果它們所代表的值通過了編譯時的檢查,那么當它們被分配給一個型別化的變數時,就會被賦予一個型別,

2.2.8 函式型別

函式型別由func關鍵字表示;它們取0個或更多的引數并回傳0個或更多的值,這些值都是要宣告型別的,

引數和回傳值決定了一個函式的型別;比如,func(string, int32)(int, error)就是輸入一個字串和一個32位有符號的整數,并回傳一個有符號的整數和一個錯誤(內置介面型別)的值的函式型別,

2.2.9 型別上的方法擴展

任何命名的型別都有一個與之相關聯的方法集合,上面的IP地址例子可以用一個檢查其值是否為已知標準的方法來擴展:

// ZeroBroadcast報告addr是否為255.255.255.255.255,
func (addr ipv4addr) ZeroBroadcast() bool {
    return addr == 0xFFFFFFFF
}

以上的函式在ipv4addr上增加了一個方法,但這個方法在uint32上沒有,

2.2.10 介面系統

Go提供了兩個功能來取代類繼承,

首先是嵌入方法,可以看成是一種自動化的構成形式或委托代理,

第二種是介面,它提供了運行時的多型性,

介面是一型別,它在Go的型別系統中提供了一種有限的結構型別化形式,

一個介面型別的物件同時也有另一種型別的定義對應,這點就像C++物件同時具有基類和派生類的特征一樣,

Go介面是在Smalltalk編程語言的協議基礎上設計的,

在描述Go介面時使用了鴨式填充這個術語,

雖然鴨式填充這個術語沒有精確的定義,它通常是說這些物件的型別一致性沒有被靜態檢查,

由于Go介面的一致性是由Go編譯器靜態地檢查的,所以Go的作者們更喜歡使用結構型別化這個詞,

介面型別的定義按名稱和型別列出了所需的方法,任何存在與介面型別I的所需方法匹配的函式的T型別的物件也是型別I的物件,型別T的定義不需要也不能識別型別I,例如,如果Shape、Square和Circle被定義為:

import "math"
 
type Shape interface {
    Area() float64
}
 
type Square struct { // 注:沒有 "實作 "宣告
    side float64
}
 
func (sq Square) Area() float64 { return sq.side * sq.side }
 
type Circle struct { // 這里也沒有 "實作 "宣告
    radius float64
}
 
func (c Circle) Area() float64 { return math.Pi * math.Pow(c.radius, 2) }
 
 

一個正方形和一個圓都隱含著一個形狀(Shape)型別,并且可以被分配給一個形狀(Shape)型別的變數,

Go的介面系統使用了了結構型別,介面也可以嵌入其他介面,其效果是創建一個組合介面,而這個組合介面正是由實作嵌入介面的型別和新定義的介面所增加的方法來滿足的,

Go標準庫在多個地方使用介面來提供通用性,這包括基于Reader和Writer概念的輸入輸出系統,

除了通過介面呼叫方法,Go還允許通過運行時型別檢查將介面值轉換為其他型別,這就是型別斷言和型別切換,

空介面{}是一個重要的基本情況,因為它可以參考任何型別的選項,它類似于Java或C#中的Object類,可以滿足任何型別,包括像int這樣的內置型別,

使用空介面的代碼不能簡單地在被參考的物件上呼叫方法或內置運算子,但它可以存盤interface{}值,通過型別斷言或型別切換嘗試將其轉換為更有用的型別,或者用Go的reflect包來檢查它,

因為 interface{} 可以參考任何值,所以它是一種擺脫靜態型別化限制的有效方式,就像C 語言中的 void*,但在運行時會有額外的型別檢查,

介面值是使用指向資料的指標和第二個指向運行時型別資訊的指標來實作的,與Go中其他一些使用指標實作的型別一樣,如果未初始化,介面值是零,

2.3 程式包系統

在Go的包系統中,每個包都有一個路徑(如"compress/bzip2 "或"golang.org/x/net/html")和一個名稱(如bzip2或html),

對其他包的定義的參考必須始終以其他包的名稱作為前綴,并且只有其他包的大寫的名稱才能被訪問:io.Reader是公開的,但bzip2.reader不是,

go get命令可以檢索存盤在遠程資源庫中的包,鼓勵開發者在開發包時,在與源資源庫相對應的基礎路徑

(如http://example.com/user_name/package_name)內開發程式包,從而減少將來在標準庫或其他外部庫中名稱碰撞的可能性,

有人提議Go引入一個合適的包管理解決方案,類似于CPANfor Perl或Rust的Cargo系統或Node的npm系統,

2.4 并發:goroutines和通道

2.4.1 【CSP并發模式】

在計算機科學中,通信順序程序(communicating sequential processes,CSP)是一種描述并發系統中互動模式的正式語言,它是并發數學理論家族中的一個成員,被稱為程序演算法(process algebras),或者說程序計算(process calculate),是基于訊息的通道傳遞的數學理論,

CSP在設計Oceam編程語言時起了很大的影響,同時也影響了Limbo、RaftLib、Go、Crystal和Clojure的core.async等編程語言的設計,

CSP最早是由TonyHoare在1978年的一篇論文中描述的,后來有了很大的發展,

CSP作為一種工具被實際應用于工業上,用于指定和驗證各種不同系統的并發功能,如T9000Transputer以及安全的電子商務系統,

CSP本身的理論目前也仍然是被積極研究的物件,包括增加其實際適用范圍的作業,如增加可分析的系統規模,

Go語言有內置的機制和庫支持來撰寫并發程式,并發不僅指的是CPU的并行性,還指的是異步性處理:讓相對慢的操作,如資料庫或網路讀取等操作在做其他作業的同時運行,這在基于事件的服務器中很常見,

主要的并發構造是goroutine,這是一種輕量級處理型別,一個以go關鍵字為前綴的函式呼叫會在一個新的goroutine中啟動這個函式,

語言規范并沒有指定如何實作goroutine,但目前的實作將Go行程的goroutine復用到一個較小的作業系統執行緒集上,類似于Erlang中的調度,

雖然一個標準的庫包具有大多數經典的并發控制結構(mutex鎖等),但Go并發程式更偏重于通道,它提供了goroutines之間的訊息傳功能,

可選的緩沖區以FIFO順序存盤訊息,允許發送的goroutines在收到訊息之前繼續進行,

通道是型別化的,所以chan T型別的通道只能用于傳輸T型別的訊息,

特殊語法約定用于對它們進行操作;<-ch是一個運算式,它使執行中的goroutine在通道ch上阻塞,直到有一個值進來,而ch<- x則是發送值x(可能阻塞直到另一個goroutine接收到這個值),

內置的類似于開關的選擇陳述句可以用來實作多通道上的非阻塞通信,Go有一個記憶體模型,描述了goroutine必須如何使用通道或其他操作來安全地共享資料,

通道的存在使Go有別于像Erlang這樣的actor模型式的并發語言,在這種語言中,訊息是直接面向actor(對應于goroutine)的,在Go中,可以通過在goroutine和通道之間保持一對一的對應關系來,Go語言也允許多個goroutine共享一個通道,或者一個goroutine在多個通道上發送和接收訊息,

通過這些功能,人們可以構建像workerpools、流水線(比如說,在下載檔案時,對檔案進行解壓縮和決議)、帶超時的后臺呼叫、對一組服務的"扇出"并行呼叫等并發構造,

通道也有一些超越行程間通信的常規概念的用途,比如作為一個并發安全的回識訓沖區串列,實作coroutines和實作迭代器,

Go的并發相關的結構約定(通道和替代通道輸入)來自于TonyHoare的通信順序行程模型,

不像以前的并發編程語言,如Occam或Limbo(Go的共同設計者RobPike曾在此基礎上作業過的語言),Go沒有提供任何內置的安全或可驗證的并發概念,

雖然在Go中,上述的通信處理模型是推薦使用的,但不是唯一的:一個程式中的所有goroutines共享一個單一的地址空間,這意味著可突變物件和指標可以在goroutines之間共享,

2.5 并行編程的舒適度

有一項研究比較了一個不熟悉Go語言的老練程式員撰寫的程式的大小(以代碼行數為單位)和速度,以及一個Go專家(來自Google開發團隊)對這些程式的修正,對Chapel、Cilk和IntelTBB做了同樣的研究,

研究發現,非專家傾向于用每個遞回中的一條Go陳述句來寫分解-解決演算法,而專家則用每個處理器的一條Go陳述句來寫分布式作業同步程式,Go專家的程式通常更快,但也更長,

2.6 條件競賽安全問題

Goroutine對于如何訪問共享資料沒有限制,這使得條件競賽成為可能的問題,

具體來說,除非程式通過通道或其他方式顯式同步,否則多個goroutine共享讀寫一個記憶體區域可能會發生問題,

此外,Go的內部資料結構,如介面值、動態陣列頭、哈希表和字串頭等內部資料結構也不能幸免于條件競賽,因此在多執行緒程式中,如果修改這些型別的共享實體沒有同步,就會存在影響型別和記憶體安全的情況,

2.7 二進制生成

gc工具鏈中的聯結器默認會創建靜態鏈接的二進制檔案,因此所有的Go二進制檔案都包括Go運行所需要的內容,

2.8 舍棄的語言特征

Go故意省略了其他語言中常見的一些功能,包括繼承、通用編程、斷言、指標運算、隱式型別轉換、無標記的聯合和標記聯合,

2.9 Go風格特點

Go作者在Go程式的風格方面付出了大量的努力:

  • gofmt工具自動規范了代碼的縮進、間距和其他表面級的細節,
  • 與Go一起分發的工具和庫推薦了一些標準的方法,比如API檔案(godoc)、 測驗(go test)、構建(go build)、包管理(go get)等等,
  • Go的一些規則跟其他語言不同,例如禁止回圈依賴、未使用的變數或匯入、隱式型別轉換等,
  • 某些特性的省略(例如,函式編程的一些捷徑,如map和Java風格的try/finally塊)編程風格顯式化,具體化,簡單化,
  • Go團隊從第一天開始就發布了一個Go的語法使用集合,后來還收集了一些代碼的評論,講座和官方博客文章,來推廣Go的風格和編碼理念,

三、【Go的工具】

主要的Go發行版包括構建、測驗和分析代碼的工具,

? go build,它只使用源檔案中的資訊來構建Go二進制檔案,不使用單獨的makefiles,

? gotest,用于單元測驗和微基準

? go fmt,用于格式化代碼

? go get,用于檢索和安裝遠程包,

? go vet,靜態分析器,查找代碼中的潛在錯誤,

? go run,構建和執行代碼的快捷方式

? godoc,用于顯示檔案或通過HTTP

? gorename,用于以型別安全的方式重命名變數、函式等,

? go generate,一個標準的呼叫代碼生成器的方法,

它還包括分析和除錯支持、運行時診斷(例如,跟蹤垃圾收集暫停)和條件競賽測驗器,

第三方工具的生態系統增強了標準的發布系統,如:

gocode,它可以在許多文本編輯器中自動完成代碼,

goimports(由Go團隊成員提供),它可以根據需要自動添加/洗掉包匯入,以及errcheck,它可以檢測可能無意中被忽略的錯誤代碼,

四、【編輯環境】

流行的Go代碼工具:

? GoLand:JetBrains公司的IDE,

? VisualStudio Code

? LiteIDE:一個"簡單、開源、跨平臺的GoIDE"

? Vim:用戶可以安裝插件:

? vim-go

五、【應用案例】

用Go撰寫的一些著名的開源應用包括:

? Caddy,一個開源的HTTP/2web服務器,具有自動HTTPS功能,

? CockroachDB,一個開源的、可生存的、強一致性、可擴展的SQL資料庫,

? Docker,一套用于部署Linux容器的工具,

? Ethereum,以太幣虛擬機區塊鏈的Go-Ethereum實作,

? Hugo,一個靜態網站生成器

? InfluxDB,一個專門用于處理高可用性和高性能要求的時間序列資料的開源資料庫,

? InterPlanetaryFile System,一個可內容尋址、點對點的超媒體協議,

? Juju,由UbuntuLinux的包裝商Canonical公司推出的服務協調工具,

? Kubernetes容器管理系統

? lnd,位元幣閃電網路的實作,

? Mattermost,一個團隊聊天系統

? NATSMessaging,是一個開源的訊息傳遞系統,其核心設計原則是性能、可擴展性和易用性,

? OpenShift,云計算服務平臺

? Snappy,一個由Canonical開發的UbuntuTouch軟體包管理器,

? Syncthing,一個開源的檔案同步客戶端/服務器應用程式,

? Terraform,是HashiCorp公司的一款開源的多云基礎設施配置工具,

其他使用Go的知名公司和網站包括:

? Cacoo,使用Go和gRPC渲染用戶儀表板頁面和微服務,

? Chango,程式化廣告公司,在其實時競價系統中使用Go,

? CloudFoundry,平臺即服務系統

? Cloudflare,三角編碼代理Railgun,分布式DNS服務,以及密碼學、日志、流處理和訪問SPDY網站的工具,

? 容器Linux(原CoreOS),是一個基于Linux的作業系統,使用Docker容器和rkt容器,

? Couchbase、Couchbase服務器內的查詢和索引服務,

? Dropbox,將部分關鍵組件從Python遷移到了Go,

? 谷歌,許多專案,特別是下載服務器dl.google.com,

? Heroku,Doozer,一個提供鎖具服務的公司

? HyperledgerFabric,一個開源的企業級分布式分類賬專案,

? MongoDB,管理MongoDB實體的工具,

? Netflix的服務器架構的兩個部分,

? Nutanix,用于其企業云作業系統中的各種微服務,

? Plug.dj,一個互動式在線社交音樂流媒體網站,

? SendGrid是一家位于科羅拉多州博爾德市的事務性電子郵件發送和管理服務,

? SoundCloud,"幾十個系統"

? Splice,其在線音樂協作平臺的整個后端(API和決議器),

? ThoughtWorks,持續傳遞和即時資訊的工具和應用(CoyIM),

? Twitch,他們基于IRC的聊天系統(從Python移植過來的),

? Uber,處理大量基于地理資訊的查詢,

六、【代碼示例】

6.1 Hello World

package main
 
import "fmt"
 
func main() {
    fmt.Println("Hello, world!")
}
 

6.2 并發

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.")
    }
}

6.3 代碼測驗

沒有測驗的代碼是不完整的,因此我們需要看看代碼測驗部分的撰寫,

代碼:

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)
            }
        })
    }
}

6.4 創建后端服務

接下來我寫一個例子創建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()
}
 

呼叫添加,更新API以后回傳所有資料的測驗結果:

七、【 褒貶不一】

7.1 贊揚

MicheleSimionato對Go大加贊揚:

介面系統簡潔,并刻意省略了繼承,

EngineYard的DaveAstels寫道:

Go是非常容易上手的,很少的基本語言概念,語法也很干凈,設計得很清晰,Go目前還是實驗性的,還有些地方比較粗糙,

2009年,Go被TIOBE編程社區指數評選為年度最佳編程語言,

到2010年1月,Go的排名達到了第13位,超過了Pascal等成熟的語言,

但到了2015年6月,它的排名跌至第50位以下,低于COBOL和Fortran,

但截至2017年1月,它的排名又飆升至第13位,顯示出它的普及率和采用率有了顯著的增長,

Go被評為2016年TIOBE年度最佳編程語言,

BruceEckel曾表示:

C++的復雜性(在新的C++中甚至增加了更多的復雜性),以及由此帶來的對生產力的影響,已經沒有任何理由繼續使用C++了,C++程式員為了克服C語言的一些問題而做出的增強初衷目前已經沒有了意義,而Go此時顯得更有意義,

2011年一位Google工程師R.Hundt對Go語言及其GC實作與C++(GCC)、Java和Scala的對比評估發現,

Go提供了有趣的語言特性,這也使得Go語言有了簡潔、標準化的特征,這種語言的編譯器還不成熟,這在性能和二進制大小上都有體現,

這一評價收到了Go開發團隊的快速反應,

IanLance Taylor因為Hundt的評論改進了Go代碼;

RussCox隨后對Go代碼以及C++代碼進行了優化,并讓Go代碼的運行速度比C++略快,比評論中使用的代碼性能快了一個數量級以上,

7.2 命名爭議

2009年11月10日,也就是Go!編程語言全面發布的當天,Go!編程語言的開發者FrancisMcCabe(注意是感嘆號)要求更改Google的語言名稱,以避免與他花了10年時間開發的語言混淆,

McCabe表示了對谷歌這個'大塊頭'最侄訓碾壓他"的擔憂,這種擔憂引起了120多名開發者的共鳴,他們在Google官方的問題執行緒上評論說他們應該改名,有些人甚至說這個問題違背了Google的座右銘:"不要作惡,"

2010年10月12日,谷歌開發者RussCox關閉了這個問題,自定義狀態為"不幸",并附上了以下評論:

"有很多計算產品和服務都被命名為Go,在我們發布以來的11個月里,這兩種語言的混淆度極低,"

7.3 【批評】

Go的批評家們的觀點:

  • 通用程式設計缺乏引數多型性,導致代碼重復或不安全的型別轉換以及擾亂流程的隨意性,
  • Go的nil,加上代數型別的缺失,導致故障處理和基本問題的避免很困難,
  • Go不允許在當前行中出現開局括號,這就迫使所有的Go程式員必須使用相同的括號樣式,

八、【小結】

本文從Go的語法,型別系統,編碼風格,語言工具,編碼工具和使用案例等幾方面對Go語言進行了學習和探討,希望可以拋磚引玉,對Go語言感興趣的同仁有所裨益,

點擊關注,第一時間了解華為云新鮮技術~

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/172383.html

標籤:其他

上一篇:fisco bcos智能合約中對tx.origin和msg.sender的作用

下一篇:Flutter--手勢

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more