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安装第三方包