1、內置函數golang
1.close數組
主要用來關閉channel數據結構
2.len閉包
用來求長度,好比:string、array、slice、map、channelapp
3.newide
用來分配內存,主要用來分配值類型,好比:int、struct。返回的是指針函數
package main import "fmt" func main(){ var a int fmt.Println(a) j := new(int) fmt.Println(j) *j = 100 fmt.Println(*j) }
4.make性能
用來分配內存,主要用來分配引用類型,好比chan、map、sliceatom
package main import "fmt" func main(){ var a []int a = make([]int,8) fmt.Println(a) a[0] = 1 fmt.Println(a) }
5.appendspa
用來追加元素到數組、slice中
func main(){ var a []int a = append(a,1) a = append(a,2) fmt.Println(a) }
6.panic和recover
用來作錯誤處理
func test(){ i := 0 j := 1000/i fmt.Println(j) } func main(){ for { test() time.Sleep(time.Second) } } //直接panic func test(){ defer func(){ if err := recover(); err != nil{ fmt.Println(err) } }() i := 0 j := 1000/i fmt.Println(j) } func main(){ for { test() time.Sleep(time.Second) } } //捕獲異常
func initConfig() (err error){ return errors.New("init config failed") } func test(){ err := initConfig() if err != nil{ panic(err) } } func main(){ for { test() time.Sleep(time.Second) } }
2、閉包
1.定義
一個函數和與其相關的引用環境組合而成的實體
2.例子
func Add() func(int) int{ var x int return func(n int) int{ x += n return x } } func main(){ f := Add() fmt.Println(f(1)) fmt.Println(f(100)) }
func makeSuffix(suffix string) func(string) string{ return func(name string) string{ if strings.HasSuffix(name, suffix) == false{ return name + suffix } return name } } func main(){ f1 := makeSuffix(".jpg") fmt.Println(f1("test1")) f2 := makeSuffix(".png") fmt.Println(f2("test2")) }
3、數組與切片
數組
1.概念
是同一種數據類型的固定長度的序列
2.定義
var a [len]int //好比:var a[5]int
3.長度是數組類型的一部分,所以,var a[5] int 和var a[10]int是不一樣的類型
4.數組能夠經過下標進行訪問,下標是從0開始,最後一個元素下標是:len-1
5.訪問越界,若是下標在數組合法範圍以外,則觸發訪問越界:會panic
6.數組是值類型,所以改變副本的值,不會改變自己的值
func t1(){ var a[5] int b := a b[0] = 100 fmt.Println(a) } func t2(a[5] int){ a[0] = 100 } func main(){ t1() var b[5] int t2(b) fmt.Println(b) } //結果 [0 0 0 0 0] [0 0 0 0 0]
7.數組的初始化
var a1 [5]int = [5]int{1,2,3,4,5} var a2 = [5]int{1,2,3,4,5} //變量名後的類型能夠省略 var a3 = [...]int{1,2,3,4,5} //長度能夠用...代替 var a4 = [5]string{3:"hello",4:"tom"} //能夠對數組某些元素進行初始化
8.多維數組
var a [5][3]int var f [2][3]int = [...][3]int{{1,2,3},{4,5,6}}
9.數組的遍歷
import "fmt" var arr1 [5]int = [5]int{1,2,3,4,5} var arr2 [2][3]int = [...][3]int{{1,2,3},{4,5,6}} func range1(){ for i := 0; i < len(arr1); i++{ fmt.Println(arr1[i]) } fmt.Println() for i := 0; i < len(arr2); i++{ for j := 0; j < len(arr2[i]); j++{ fmt.Println(arr2[i][j]) } } } func range2(){ for i, v := range arr1{ fmt.Printf("index:%v,value:%v\n",i,v) } fmt.Println() for _, v := range arr2{ for i, v2 := range v{ fmt.Printf("index:%v,value:%v\n",i,v2) } } } func main(){ range1() range2() }
切片
1.概念:是數組的一個引用,所以切片是引用類型
package main import "fmt" func main(){ var arr = [5]int{1,2,3,4,5} var slice []int = arr[:] modify(slice) fmt.Println(slice) } func modify(slice []int){ slice[0] = 100 } //結果 [100 2 3 4 5]
2.切片的長度能夠改變,所以切片是一個可變的數組
func main(){ var arr = [5]int{1,2,3,4,5} var slice []int = arr[:] fmt.Printf("切片:%v,長度:%v,容量:%v\n",slice,len(slice),cap(slice)) fmt.Printf("slice地址:%p,數組第一個元素地址:%p\n",slice,&arr[0]) slice = append(slice,1) fmt.Printf("切片:%v,長度:%v,容量:%v\n",slice,len(slice),cap(slice)) fmt.Printf("slice地址:%p,數組第一個元素地址:%p\n",slice,&arr[0]) } /* 結果 切片:[1 2 3 4 5],長度:5,容量:5 slice地址:0xc000070030,數組第一個元素地址:0xc000070030 切片:[1 2 3 4 5 1],長度:6,容量:10 slice地址:0xc000084000,數組第一個元素地址:0xc000070030 */ //能夠看出,切片的長度是可變的,會進行擴容,最初,切片的指針指向數組中對應元素的地址,而擴容是從新開闢一個內存空間,對數組進行重拷貝的過程
3.切片遍歷方式和數組同樣,能夠用len()求長度
4.cap能夠求出slice最大的容量, 0 <= len(slice) <= cap(arry),其中arry是slice引用的數組
5.切片的定義:var 變量名 []類型,好比:var str []string
6.切片初始化:var slice []int = arr[start:end],顧頭不顧尾
7.
var slice []int = arr[0,len(arr)] 能夠簡寫爲:var slice []int = arr[:]
8.若是要把最後一個元素去掉,能夠這麼寫:slice = slice[:len(slice)-1]
9.除了數組建立切片的方式外,也能夠經過make建立
var slice []type = make([]type,len) slice := make([]type, len) slice := make([]type, len, cap)
func main(){ var slice1 = make([]int, 5) fmt.Println(slice1) slice2 := make([]int, 5) fmt.Println(slice2) slice3 := make([]int, 2, 5) fmt.Println(slice3) }
10.用append內置函數操做切片
slice = append(slice,10) var a = []int{1,2,3} var b = []int{4,5,6} a = a.append(a,b...)
11.切片的底層結構
struct{ ptr //指向數組 len cap }
12.切片resize
func main(){ var arr = [5]int{1,2,3,4,5} slice := arr[:len(arr)-1] fmt.Printf("slice:%v,len:%v,cap:%v\n",slice,len(slice),cap(slice)) slice = slice[1:] fmt.Printf("slice:%v,len:%v,cap:%v\n",slice,len(slice),cap(slice)) } /* slice:[1 2 3 4],len:4,cap:5 slice:[2 3 4],len:3,cap:4 */
13.切片的拷貝
func main(){ var arr = [5]int{1,2,3,4,5} slice1 := arr[:] slice2 := make([]int,4) copy(slice2,slice1) fmt.Println(slice2) } /* [1,2,3,4] */
14.string與slice
string底層就是一個byte的數組,所以也能夠進行切片
排序和查找
sort.Ints對整數進行排序,sort.String對字符串進行排序,sort.Float64s對浮點數進行排序
func main(){ slice := []int{5,2,6,3,7} sort.Ints(slice) fmt.Println(slice) }
sort.SearchInts(a []int, b int)從數組a中查找b,前提是a必須有序
SearchInts 在ints切片中搜索x並返回索引 如Search函數所述. 返回能夠插入x值的索引位置,若是x 不存在,返回數組a的長度 切片必須以升序排列
func main(){ slice := []int{5,2,6,3,7} sort.Ints(slice) fmt.Println(slice) ind := sort.SearchInts(slice,2) fmt.Println(ind) }
sort.Floats(a []int, b int)從數組a中查找b,前提是a必須有序
其它詳見文檔:http://docscn.studygolang.com/pkg/sort/
4、map
1.概念:key-value的數據結構,又叫字典或者關聯數組
2.聲明
var 變量名 map[keytype]valuetype //聲明是不會分配內存的,初始化須要make
3.相關操做
func main(){ var map1 = map[string]string{"hello":"china"} var map2 map[string]string map2 = make(map[string]string,5) fmt.Println(map1,map2) //插入和更新 map2["age"] = "18" fmt.Println(map1,map2) //查找 _, ok := map2["name"] if !ok{ fmt.Println("不存在") } //遍歷 for k, v := range map2{ fmt.Println(k, v) } //長度 fmt.Println(len(map2)) //刪除 delete(map2,"age") fmt.Println(map2) }
4.map是一個引用類型
func modify(map1 map[string]string){ _, ok := map1["salary"] if !ok{ map1["salary"] = "0" } } func main(){ map1 := map[string]string{"name":"bob","age":"32"} modify(map1) fmt.Println(map1) }
5.map排序
先獲取因此key,把key進行排序
按照排序好的key,進行遍歷
6.map反轉
初始化另外一個map,把key、value交換
5、包
線程同步:sync
互斥鎖,var mu sync.Mutex
讀寫鎖,var mu sync.RWMutex
讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分紅讀者和寫者,讀者只對共享資源進行讀訪問,寫者則須要對共享資源進行寫操做。
一次只有一個線程能夠佔有寫模式的讀寫鎖, 可是能夠有多個線程同時佔有讀模式的讀寫鎖.
package main import ( "fmt" "time" "sync" ) var lock sync.Mutex func main(){ a := 1 for i := 0; i<2; i++{ go func(a *int){ //對共享資源加鎖 lock.Lock() *a-- lock.Unlock() }(&a) } time.Sleep(time.Second) lock.Lock() fmt.Println(a) lock.Unlock() } //在編譯的時候使用--race
//讀多寫少的狀況下 package main import ( "fmt" "time" "sync" "sync/atomic" ) // var lock sync.Mutex var relock sync.RWMutex var ctn int32 func testRWMutex(){ map1 := map[int]int{ 0:1, 1:6, 2:7, } for i := 0; i < 100; i++{ go func(a map[int]int){ for{ relock.RLock() time.Sleep(time.Millisecond) relock.RUnlock() atomic.AddInt32(&ctn,1) } }(map1) } time.Sleep(time.Second*3) fmt.Println(atomic.LoadInt32(&ctn)) } func main(){ testRWMutex() } //使用讀寫鎖運行了162302次 package main import ( "fmt" "time" "sync" "sync/atomic" ) var lock sync.Mutex // var relock sync.RWMutex var ctn int32 func testRWMutex(){ map1 := map[int]int{ 0:1, 1:6, 2:7, } for i := 0; i < 100; i++{ go func(a map[int]int){ for{ lock.Lock() time.Sleep(time.Millisecond) lock.Unlock() atomic.AddInt32(&ctn,1) } }(map1) } time.Sleep(time.Second*3) fmt.Println(atomic.LoadInt32(&ctn)) } func main(){ testRWMutex() } //使用互斥鎖運行了1699次
go get安裝第三方包