golang 特性簡介
golang 特性簡介
by sheepbao
主要大概介紹 go 語言的歷史和特性,簡單的入門。
來歷
很久以前,有一個 IT 公司,這公司有個傳統,允許員工擁有 20% 自由時間來開發實驗性專案。在 2007 的某一天,公司的幾個大牛,正在用 c++ 開發一些比較繁瑣但是核心的工作,主要包括龐大的分散式叢集,大牛覺得很鬧心,後來 c++ 委員會來他們公司演講,說 c++ 將要新增大概 35 種新特性。這幾個大牛的其中一個人,名為:Rob Pike,聽後心中一萬個 xxx 飄過,“c++ 特性還不夠多嗎?簡化 c++ 應該更有成就感吧”。於是乎,Rob Pike 和其他幾個大牛討論了一下,怎麼解決這個問題,過了一會,Rob Pike 說要不我們自己搞個語言吧,名字叫 “go”,非常簡短,容易拼寫。其他幾位大牛就說好啊,然後他們找了塊白板,在上面寫下希望能有哪些功能(詳見文尾)。接下來的時間裡,大牛們開心的討論設計這門語言的特性,經過漫長的歲月,他們決定,以 c 語言為原型,以及借鑑其他語言的一些特性,來解放程式設計師,解放自己,然後在 2009 年,go 語言誕生。
思想
Less can be more
大道至簡,小而蘊真
讓事情變得複雜很容易,讓事情變得簡單才難
深刻的工程文化
優點
- 自帶 gc。
- 靜態編譯,編譯好後,扔伺服器直接執行。
- 簡單的思想,沒有繼承,多型,類等。
- 豐富的庫和詳細的開發文件。
- 語法層支援併發,和擁有同步併發的 channel 型別,使併發開發變得非常方便。
- 簡潔的語法,提高開發效率,同時提高程式碼的閱讀性和可維護性。
- 超級簡單的交叉編譯,僅需更改環境變數。(花了我兩天時間編譯一個 imagemagick 到 arm 平臺)
- 內含完善、全面的軟體工程工具。Go 語言自帶的命令和工具相當地強大。通過它們,我們可以很輕鬆地完成 Go 語言程式的獲取、編譯、測試、安裝、執行、執行分析等一系列工作,這幾乎涉及了開發和維護一個軟體的所有環節。
hello
package main
func main(){
println("hello, sewise")
}
type
主要講講特有的型別,其他基本型別不做介紹
slice
切片:可以理解為動態陣列,類似 c++ 的 vector 宣告一個 slice
var slice []T
如:
var ints []int
slice 的追加
ints=append(ints,1)
ints=append(ints,2,3,4,5)
slice 的擷取
newInts1:=ints[2:3]
newInts2:=ints[2:]
newInts3:=ints[:4]
map
字典:鍵值對
var json map[string]string
interface
介面:方法的集合,是一種合約
栗子: 宣告一個bird
介面
var bird interface{
fly()
}
宣告一個hen
物件 (實現 bird 介面)
type hen struct {
weight int
hasFeather bool
}
func (h hen)fly(){
fmt.Println("iI can fly")
}
type func (h hen)eat(){
h.weight++
fmt.Println("yes, I can eat")
}
宣告一個pig
物件 (未實現 bird 介面,因為 pig 不會 fly)
type pig struct {
age int
weignt int
hasFeather bool
}
func (p pig)run(){
fmt.Println("I can run")
}
func (p pig)eat(){
p.weight += 100
fmt.Println("Yes, I can eat so much")
}
func (p pig)sleep(){
fmt.Println("I slept all my life")
}
// pig can't fly
channel
通道:輕量集佇列,傳遞某種型別的值的通道
var ch chan int
ch=make(chan int,1)
往 ch 寫入一個資料
ch<-8888
從 ch 讀取資料
out:=<-ch
特性: channel 是有長度的,當 channel 的緩衝為滿時,再往裡寫入就會阻塞,當 channel 的緩衝為空時,從 channel 讀就會阻塞
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
fmt.Println("ch len:", len(ch))
go func() {
// 往緩衝滿的channel裡寫資料(阻塞)
// ch <- 1
// 從緩衝為空的channel裡讀資料(阻塞)
<-ch
fmt.Println("I am in minor goroutine")
}()
fmt.Println("I am in main goroutine")
time.Sleep(2 * time.Second)
}
當長度為 0 是,就是不帶緩衝的 channel 長度大於 0,就是帶緩衝的 channel
併發
關鍵字:go
啟動 go 程
一個普通的函式或方法呼叫前加上關鍵字 go,即可啟動一個 goroutine
go func(){
fmt.Println("start func")
time.Sleep(120*time.Second)
}()
競爭條件檢測
-race
race.go
package main
import (
"fmt"
"time"
)
func main() {
a := 1
go func() {
a = 2
}()
a = 3
fmt.Println("a is ", a)
time.Sleep(2 * time.Second)
}
檢測:執行go run -race race.go
a is 3
==================
WARNING: DATA RACE
Write at 0x00c420072188 by goroutine 6:
main.main.func1()
/Users/bao/program/go/gowork/hello/src/research/race.go:11 +0x3b
Previous write at 0x00c420072188 by main goroutine:
main.main()
/Users/bao/program/go/gowork/hello/src/research/race.go:13 +0x9f
Goroutine 6 (running) created at:
main.main()
/Users/bao/program/go/gowork/hello/src/research/race.go:12 +0x8e
==================
Found 1 data race(s)
結果分析: goroutine6 執行到第 11 行和 main goroutine 執行到 13 行的時候觸發競爭了。而且 goroutine6 是在第 12 行的時候產生的。
package
包的管理,關鍵字import
,GOPATH
gopath
gopath 是一個路徑列表,存放 go 專案工程
GOPATH
檔案目錄結構
├── bin 二進位制檔案目錄
├── pkg 編譯好的庫檔案目錄
└── src 原始碼目錄
平常專案的目錄結構
├── bin 二進位制檔案目錄
├── pkg 編譯好的庫檔案目錄
└── src 原始碼目錄
├── main 入口函式目錄
└── vendor 當前專案的庫目錄
└── sheepbao.com
└── glog
import
比如上面的專案,我要在main.go
引入glog
包
package main
// 引入glog包
import "sheepbao.com/glog"
func main(){
glog.Println("test")
}
go 的工程工具簡介
test
go 的命令工具 test
,用來做測試
單元測試
go test
只測試函式名被它正確匹配的測試函式
go test -v -run="French|Canal"
栗子: add.go
package test
func addOne(i int) int {
return i + 1
}
add_test.go
package test
import "testing"
func TestAddOne(t *testing.T) {
result := addOne(1)
if result != 2 {
t.Error("1+1!=2")
}
}
bao@baoMac test$ go test -v .
=== RUN TestAddOne
--- PASS: TestAddOne (0.00s)
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/test 0.006s
基準測試
go test -bench=.
記憶體的分配情況
go test -bench=FuncName -benchmem
栗子: stringsCon.go
package bench
import (
"fmt"
)
func Sprintf(s1, s2, s3 string) string {
return fmt.Sprintf("%s%s%s", s1, s2, s3)
}
func AddString(s1, s2, s3 string) string {
return s1 + s2 + s3
}
stringCon_test.go
package bench
import "testing"
var (
s1 = "make it run!"
s2 = "make it right!"
s3 = "make it fast!"
)
func BenchmarkSprintf(b *testing.B) {
for i := 0; i < b.N; i++ {
Sprintf(s1, s2, s3)
}
}
func BenchmarkAddString(b *testing.B) {
for i := 0; i < b.N; i++ {
AddString(s1, s2, s3)
}
}
go test -bench=.
bao@baoMac bench$ go test -bench=.
testing: warning: no tests to run
BenchmarkSprintf-4 5000000 349 ns/op
BenchmarkAddString-4 20000000 61.7 ns/op
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/bench 3.414s
樣本測試
package et
import (
"fmt"
)
func ExampleHello() {
fmt.Println("hello, sewise")
// Output: hello, sewise
}
bao@baoMac example$ go test -v .
=== RUN ExampleHello
--- PASS: ExampleHello (0.00s)
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/example 0.006s
如果把上面的// Output: hello, sewise
改為// Output: hello, sewis
則樣本測試不能通過
bao@baoMac example$ go test -v .
=== RUN ExampleHello
--- FAIL: ExampleHello (0.00s)
got:
hello, sewise
want:
hello, sewis
FAIL
exit status 1
FAIL _/Users/bao/program/go/gowork/hello/src/research/example 0.006s
pprof
go 的命令工具 pprof
,用來效能分析(記憶體使用,洩露和 cpu 消耗)
go tool pprof
- 檢視 cpu 使用:
go tool pprof http://localhost:8089/debug/pprof/profile
終端檢視:
視覺化 (原是 svg 檔案,下圖為截圖):
- 檢視記憶體使用
go tool pprof http://localhost:8089/debug/pprof/heap
終端檢視:
視覺化 (原是 svg 檔案,下圖為截圖:
go tool pprof --text http://localhost:6060/debug/pprof/heap
資料
http://www.csdn.net/article/2012-07-04/2807113-less-is-exponentially-more
http://smallsoho.com/2016/11/20/Go.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io簡明教程
大牛真身
最大牌的當屬 B 和 C 語言設計者、Unix 和 Plan 9 創始人、1983 年圖靈獎獲得者 Ken Thompson,這份名單中還包括了 Unix 核心成員 Rob Pike(go 語言之父)、java HotSpot 虛擬機器和 js v8 引擎的開發者 Robert Griesemer、Memcached 作者 Brad Fitzpatrick,等等。
功能
- 規範的語法(不需要符號表來解析)
- 垃圾回收(獨有)
- 無標頭檔案
- 明確的依賴
- 無迴圈依賴
- 常量只能是數字
- int 和 int32 是兩種型別
- 字母大小寫設定可見性(letter case sets visibility)
- 任何型別(type)都有方法(不是型別)
- 沒有子型別繼承(不是子類)
- 包級別初始化以及明確的初始化順序
- 檔案被編譯到一個包裡
- 包 package-level globals presented in any order
- 沒有數值型別轉換(常量起輔助作用)
- 介面隱式實現(沒有 “implement” 宣告)
- 嵌入(不會提升到超類)
- 方法按照函式宣告(沒有特別的位置要求)
- 方法即函式
- 介面只有方法(沒有資料)
- 方法通過名字匹配(而非型別)
- 沒有建構函式和解構函式
- postincrement(如 ++i)是狀態,不是表示式
- 沒有 preincrement(i++) 和 predecrement
- 賦值不是表示式
- 明確賦值和函式呼叫中的計算順序(沒有 “sequence point”)
- 沒有指標運算
- 記憶體一直以零值初始化
- 區域性變數取值合法
- 方法中沒有 “this”
- 分段的堆疊
- 沒有靜態和其它型別的註釋
- 沒有模板
- 內建 string、slice 和 map
- 陣列邊界檢查
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- Golang : pflag 包簡介Golang
- Golang : cobra 包簡介Golang
- Redis GEO 特性簡介Redis
- MySQL 5.7的主要特性簡介MySql
- ECMAScript各版本簡介及特性
- GOLANG簡介與基礎語法Golang
- Oracle 11g 新特性簡介Oracle
- golang Leaf 遊戲伺服器框架簡介Golang遊戲伺服器框架
- Golang | 簡介channel常見用法,完成goroutin通訊Golang
- 簡單介紹如何使用Bazel構建Golang程式Golang
- ES2015新特性簡介
- 12c新特性-Oracle Sharding簡介Oracle
- 簡短介紹 C# 6 的新特性C#
- oracle glodendate產品的公司簡介和特性Oracle
- golang 物件導向特性Golang物件
- Golang Agent 可觀測性的全面升級與新特性介紹Golang
- 『簡書API:jianshu 基於golang -- 用法介紹 (2)』APIGolang
- ECMAScript 2017(ES8)新特性簡介
- ECMAScript 2021(ES12)新特性簡介
- Oracle:19c 新特性——Memoptimized Rowstore 簡介OracleZed
- Oracle 11g 新特性 – HM(Hang Manager)簡介Oracle
- Golang Tools 介紹Golang
- ECMAScript 2016(ES7)新特性簡介
- ECMAScript 2019(ES10)新特性簡介
- ECMAScript 2018(ES9)新特性簡介
- ECMAScript 2020(ES11)新特性簡介
- 簡單介紹Golang切片刪除指定元素的三種方法Golang
- 【DATAGUARD】DG系列之11g新特性簡單介紹
- IBM Lotus Quickr 8.5 for Portal 新功能和新特性簡介IBMUI
- Oracle 10G First Release的新特性簡介(下) (轉)Oracle 10g
- Oracle 10G First Release的新特性簡介(上) (轉)Oracle 10g
- 專案管理工具的特性簡要介紹(轉)專案管理
- MyRocksTTL特性介紹
- golang1.16新特性速覽Golang
- 簡單介紹Golang列印複雜結構體的兩種方法Golang結構體
- 【RAC】11gR2 新特性:Oracle Cluster Health Monitor(CHM)簡介Oracle
- golang flag簡單用法Golang
- HashSet的特性介紹