golang 簡介

golang 簡介

來歷

好久之前,有一個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

優勢

  1. 自帶gc。
  2. 靜態編譯,編譯好後,扔服務器直接運行。
  3. 簡單的思想,沒有繼承,多態,類等。
  4. 豐富的庫和詳細的開發文檔。
  5. 語法層支持併發,和擁有同步併發的channel類型,使併發開發變得很是方便。
  6. 簡潔的語法,提升開發效率,同時提升代碼的閱讀性和可維護性。
  7. 超級簡單的交叉編譯,僅需更改環境變量。(花了我兩天時間編譯一個imagemagick到arm平臺)
  8. 內含完善、全面的軟件工程工具。Go語言自帶的命令和工具至關地強大。經過它們,咱們能夠很輕鬆地完成Go語言程序的獲取、編譯、測試、安裝、運行、運行分析等一系列工做,這幾乎涉及了開發和維護一個軟件的全部環節。

hello

package main

func main(){
    println("hello, sewise")
}

type

主要講講特有的類型,其餘基本類型不作介紹c++

slice

切片:能夠理解爲動態數組,相似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]

map

字典:鍵值對golang

var json map[string]string

interface

接口:方法的集合,是一種合約 栗子: 聲明一個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

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

包的管理,關鍵字importGOPATH

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 終端查看: image_1b72f0lh9tir1prf1r2012codlt13.png-164.9kB

可視化(原是svg文件,下圖爲截圖):

image_1b72f233avto14d7on4h3nlm51g.png-129.8kB

  • 查看內存使用 go tool pprof http://localhost:8089/debug/pprof/heap 終端查看: image_1b72elqek180t8b315kn20hhlr9.png-177.3kB

可視化(原是svg文件,下圖爲截圖:

image_1b72euk7b1knr1d1n1ugq2pe19kim.png-176.7kB

go tool pprof --text http://localhost:6060/debug/pprof/heap

go命令教程

資料

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

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

  • 數組邊界檢查

相關文章
相關標籤/搜索