好久之前,有一個IT公司,這公司有個傳統,容許員工擁有20%自由時間來開發實驗性項目。在2007的某一天,公司的幾個大牛,正在用c++開發一些比較繁瑣可是核心的工做,主要包括龐大的分佈式集羣,大牛以爲很鬧心,後來c++委員會來他們公司演講,說c++將要添加大概35種新特性。這幾個大牛的其中一我的,名爲:Rob Pike,聽後心中一萬個xxx飄過,「c++特性還不夠多嗎?簡化c++應該更有成就感吧」。因而乎,Rob Pike和其餘幾個大牛討論了一下,怎麼解決這個問題,過了一會,Rob Pike說要不咱們本身搞個語言吧,名字叫「go」,很是簡短,容易拼寫。其餘幾位大牛就說好啊,而後他們找了塊白板,在上面寫下但願能有哪些功能(詳見問尾)。接下來的時間裏,大牛們開心的討論設計這門語言的特性,通過漫長的歲月,他們決定,以c語言爲原型,以及借鑑其餘語言的一些特性,來解放程序員,解放本身,而後在2009年,go語言誕生。html
Less can be more 大道至簡,小而蘊真 讓事情變得複雜很容易,讓事情變得簡單才難 深入的工程文化java
package main func main(){ println("hello, sewise") }
主要講講特有的類型,其餘基本類型不作介紹c++
切片:能夠理解爲動態數組,相似c++的vector 聲明一個slicegit
var slice []T 如: var ints []int
slice的追加程序員
ints=append(ints,1) ints=append(ints,2,3,4,5)
slice的截取github
newInts1:=ints[2:3] newInts2:=ints[2:] newInts3:=ints[:4]
字典:鍵值對golang
var json map[string]string
接口:方法的集合,是一種合約 栗子: 聲明一個bird
接口json
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
通道:輕量集隊列,傳遞某種類型的值的通道
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行的時候產生的。
包的管理,關鍵字import
,GOPATH
gopath是一個路徑列表,存放go項目工程 GOPATH
文件目錄結構
├── bin 二進制文件目錄 ├── pkg 編譯好的庫文件目錄 └── src 源碼目錄
日常項目的目錄結構
├── bin 二進制文件目錄 ├── pkg 編譯好的庫文件目錄 └── src 源碼目錄 ├── main 入口函數目錄 └── vendor 當前項目的庫目錄 └── sheepbao.com └── glog
好比上面的項目,我要在main.go
引入glog
包
package main // 引入glog包 import "sheepbao.com/glog" func main(){ glog.Println("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
go的命令工具 pprof
,用來性能分析(內存使用,泄露和cpu消耗) go tool pprof
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://www.jianshu.com/p/91e40c3e3acb?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
數組邊界檢查