《Google Go: A Primer》學習筆記

#What is Go? simple,fast,safe and concurrent #Reading Go 編輯hello.gophp

package main
import "fmt"
func main(){
    fmt.Println("Hello World!你好,世界!")
}
經典的Hello World

運行hello.go: 方式一、編程

go run hello.go
超快的編譯速度,使得go能夠像php同樣執行

方式二、數組

go build hello.go
./hello
編譯執行,go能夠像C、C++同樣發佈

#Variable Declarations安全

var sum int
var total int=42
var a,b *int
var label="name"
name:="Samuel"
像Python同樣方便的變量初始化

#Conditionals多線程

result:=someFunc()
if result>0{
    fmt.Println("result>0")
}else{
    fmt.Println("result<=0")
}
fmt.Println(result)
if result:=someFunc();result>0{
    fmt.Println("result>0")
}else{
    fmt.Println("result<=0")
}
if someFunc()>0{
    fmt.Println("result>0")
}else{
    fmt.Println("result<=0")
}
if a>0{
    fmt.Println("positive")
}else if a<0{
    fmt.Println("negative")
}else{
    fmt.Println("zero")
}

#Switches閉包

byte:='b'
var result int
switch byte{
case 'a','b':
    result=1
default:
    result=0
}
fmt.Println(result)
switch result:=calculate();true{
case result<0:
    fmt.Println("negative")
case result>0:
    fmt.Println("positive")
default:
    fmt.Println("zero")
}
switch result:=calculate();{
case result<0:
    fmt.Println("negative")
case result>0:
    fmt.Println("positive")
default:
    fmt.Println("zero")
}
switch calculate();{
case result<0:
    fmt.Println("negative")
case result>0:
    fmt.Println("positive")
default:
    fmt.Println("zero")
}
方便的switch

#Loops ##Condition併發

a:=10
b:=0
for a>b{
    fmt.Println(a,b)
    a--
    b++
}

##Initializer,Condition and Step編程語言

for i:=0;i<10;i++{
    fmt.Println(i)
}

##Rangeide

for i:=range "hello"{
    fmt.Println(i)
}

輸出0到4函數式編程

for i,ch:=range "hello"{
    fmt.Printf("%d,%c\n",i,ch)
}

##Infinite

i:=0
for{
    if i>=10{
        break
    }
    fmt.Println(i)
    i++
}
全部編程語言中最簡單的循環

#Funtions

func add(a,b int)int{
    return a+b
}
fmt.Println(add(1,2))
支持C風格的函數定義
add:=func(a,b int)int{
    return a+b
}
fmt.Println(add(1,2))
支持匿名函數定義

##Multiple Return Values

func divide(a,b int)(int,int){
    quotient:=a/b
    remainder:=a%b
    return quotient,remainder
}
func divide(a,b int)(quotient,remainder int){
    quotient=a/b
    remainder=a%b
    return quotient,remainder
}
fmt.Println(divide(7,2))
quotient,_:=divide(18,4)
支持返回值名稱
func moreMagic()(int,bool){
    return 7,true
}
if result,ok:=moreMagic();ok{
    fmt.Println(result)
}
go多返回值使錯誤處理變得簡單、高效

##Anonymous Functions

func makeAdder(x int)(func(int)int){
    return func(y int)int{return x+y}
}
add5:=makeAdder(5)
add36:=makeAdder(36)
fmt.Println("The answer:",add5(add36(1)))
支持閉包,纔是真正地支持匿名函數。
package main
import "fmt"
func main(){
    for i:=0;i<10;i++{
        defer fmt.Println("Hello",i)
        fmt.Println("World")
    }
}

輸出10個World、10個Hello

函數結束執行defer
package main
import "fmt"
func main(){
    for i:=0;i<10;i++{
        func(){
            defer fmt.Println("Hello",i)
            fmt.Println("World")
        }()
    }
}

輸出10個World、Hello

defer和匿名函數能夠徹底實現RAII、徹底實現try finally。讀者能夠舉出RAII/try finally的例子,我採用defer和匿名函數實現。

#Primitive Types ##Arrays & Slices

a:=[...]int{1,2,3,4,5,6,7,8,9,0}
fmt.Println(a)
fmt.Println(len(a))
s:=a[3:5]
fmt.Println(s)
fmt.Println(len(s))
fmt.Println(cap(s))
s=a[3:]
fmt.Println(s)
fmt.Println(len(s))
fmt.Println(cap(s))
相似Python的數組切片
s[0]=42
fmt.Println(a[3])
s=s[1:]
fmt.Println(s)
s1:=[]int{1,2,3,4,5};
fmt.Println(s1)
s2:=make([]int,10)
fmt.Println(s2)

##Maps

內置字典很是重要。C++ STL中map採用庫實現,比本身手工實現的紅黑樹速度慢;多線程併發須要互斥鎖鎖死,致使速度更慢。go的Maps線程安全,並有可能實現高效。
m:=make(map[string]int)
m["foo"]=42
m["bar"]=30
fmt.Println(m["foo"])
寫字典
x,ok:=m["bar"]
fmt.Println(x,ok)
讀字典
_,ok=m["baz"]
fmt.Println(ok)
m["foo"]=0
_,ok=m["foo"]
fmt.Println(ok)
delete(m,"bar")
x,ok=m["bar"]
fmt.Println(x,ok)
刪除字典數據,能夠看做一種讀字典

#Object Orientation ##Structs

type Point struct{
    x,y float64
}
var p *Point=new(Point)
fmt.Println(p)
var p1 Point=Point{3,4}
fmt.Println(p1)
var p2 *Point=&Point{3,4}
fmt.Println(p2)
p3:=Point{3,4}
fmt.Println(p3)
p4:=&Point{3,4}
fmt.Println(p4)
p5:=&Point{x:3,y:4}
fmt.Println(p5)

##Methods

func (self *Point) SetX(x float64) {
    self.x = x
}

修改對象須要引用語義。

func (self Point) Length() float64 {
    return math.Sqrt(self.x*self.x + self.y*self.y)
}
獲取對象數據只須要值語義。
p := &Point{3, 4}
fmt.Println(p, p.Length())
p.SetX(5)
fmt.Println(p, p.Length())

##Interfaces 面向接口很重要

依賴倒置原則:
高層次的模塊不該該依賴於低層次的模塊,他們都應該依賴於抽象。
抽象不該該依賴於具體實現,具體實現應該依賴於抽象。
package main
import (
    "bufio"
    "fmt"
    "os"
)
type Widget struct{}
func (Widget)Frob(){
    fmt.Println("Widget.Frob")
}
type Sprocket struct{}
func (Sprocket)Frob(){
    fmt.Println("Sprocket.Frob")
}
type Frobber interface{
    Frob()
}
func frobtastic(f Frobber){
    f.Frob()
}
func main(){
    var f Frobber
    reader:=bufio.NewReader(os.Stdin)
    b,_,_:=reader.ReadLine()
    line:=string(b)
    if line=="Widget"{
        f=&Widget{}
    }else if line=="Sprocket"{
        f=&Sprocket{}
    }else{
        return
    }
    frobtastic(f)
}

It is important to note that every object implements the empty interface: interface {}

go實現了非嵌入式接口,即實現了模板編程,又統一了面向對象編程和模板編程。

##Inheritance

type Base struct {
    i int
}
func (b Base) Magic() {
    fmt.Println("base magic", b.i)
}
func (self Base) MoreMagic() {
    self.Magic()
    self.Magic()
}
type Foo struct {
    Base
}
func (f Foo) Magic() {
    fmt.Println("foo magic", f.i)
}
f := &Foo{Base{1}}
f.Magic()
f.MoreMagic()
注意go沒有虛函數。

#Concurrency Do not communicate by sharing memory; instead, share memory by communicating. 不要經過共享內存來通訊,而應該經過通訊來共享內存。 ##Goroutines

package main
import ("fmt";"time")
func DoThis(){
    for i:=0;i<10;i++{
        fmt.Println("DoThis",i)
        time.Sleep(1e3)
    }
}
func main(){
    go func(){
        for i:=0;i<10;i++{
            fmt.Println("func",i)
            time.Sleep(1e3)
        }
    }()
    go DoThis()
    time.Sleep(1e9)
}

##Channels

package main
import ("fmt";"runtime")
func DoThis(ch chan int){
    result:=0
    for i:=0;i<1000000;i++{
        result+=i
    }
    ch<-result
}
func main(){
    runtime.GOMAXPROCS(runtime.NumCPU())
    ch:=make(chan int,5)
    go func(){
        result:=0
        for i:=0;i<1000000;i++{
            result+=i
        }
        ch<-result
    }()
    go DoThis(ch)
    fmt.Println(<-ch)
    val,ok:=<-ch
    fmt.Println(val,ok)
}
chan是生產者消費者的一個實現。
runtime.GOMAXPROCS支持動態設置,go多核並行。
ch := make(chan int)
go func() {
    time.Sleep(time.Second * 5)
    ch <- 0
}()
select {
case <-time.After(time.Second * 2):
    fmt.Println("timeout")
case i := <-ch:
    fmt.Println(i)
}
chan能夠實現超時

單向channel:

ch4:=make(chan int)
ch5:=<-chan int(ch4)		//單向讀取
ch6:=chan<- int(ch4)		//單向寫入
C/C++中const實現語法級肯定數據流向是個坑,單向channel很好地解決了這個問題。

關閉channel:

close(ch)
func fibonacci(n int, c chan int) {
    x, y := 1, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
    fmt.Println(i)
}
面向數據流編程比面向對象編程能夠更清晰地解決後臺問題。

讓出時間片:

func say(s string) {
    for i := 0; i < 5; i++ {
        runtime.Gosched()
        fmt.Println(s)
    }
}
runtime.GOMAXPROCS(1)
go say("World")
say("Hello")

同步鎖:sync.Mutex、sync.RWMutex 全局惟一性操做:

var once sync.Once		//全局
once.Do(setup)
C、C++、Java、C#、go等語言都提供了單例模式的實現。

#Packages

src
	main
		hello.go
	Point
		Point.go
export GOPATH=src父目錄的全路徑

編輯Point.go

Package Point
import "math"
type Point struct{
    x,y float64
}
func NewPoint(x,y float64)*Point{
    return &Point{x,y}
}
func (self Point)Length()float64{
    return math.Sqrt(self.x*self.y+self.y*self.y)
}
func (self *Point)Scale(factor float64){
    self.setX(self.x*factor)
    self.setY(self.y*factor)
}
func (self *Point)setX(x float64){
    self.x=x
}
func (self *Point)setY(y float64){
    self.y=y
}

編輯hello.go

package main
import ("fmt";"Point")
func main(){
    p:=Point.NewPoint(3,4)
    fmt.Println(p.Length())
    p.Scale(10.0)
    fmt.Println(p.Length())
}

運行: 方式1、

go run hello.go

方式2、

go build hello.go
./hello

#What's Missing #總結

  • go支持過程化編程、面向對象編程、函數式編程
  • go支持面向接口編程、模板編程、面向數據流編程
  • go語法比C更明確,比Python更簡單
  • go內存自動回收、defer資源回收、支持RAII、支持try finally
  • go簡化了錯誤處理
  • go內置了數組、數組切片、字典
  • go提供了協程、生產者消費者、互斥鎖、讀寫鎖、高效多核並行
  • go內置了工程管理工具 Less is more的思想正如《道德經》:
大音希聲,大象無形。
相關文章
相關標籤/搜索