Go內置函數、數組與切片、map、包

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)
}
View Code

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)
}
View Code

5.appendspa

用來追加元素到數組、slice中

func main(){
    var a []int
    a = append(a,1)
    a = append(a,2)
    fmt.Println(a)
}
View Code

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)
    }
}
//捕獲異常
View Code
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)
    }
}
自定義panic

 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))
}
View Code
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"))
}
View Code

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]
View Code

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()
}
View Code

切片

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]
View Code

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
*/

//能夠看出,切片的長度是可變的,會進行擴容,最初,切片的指針指向數組中對應元素的地址,而擴容是從新開闢一個內存空間,對數組進行重拷貝的過程
View Code

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 包爲切片及用戶定義的集合的排序操做提供了原語.

sort.Ints對整數進行排序,sort.String對字符串進行排序,sort.Float64s對浮點數進行排序

func main(){
    slice := []int{5,2,6,3,7}
    sort.Ints(slice)
    fmt.Println(slice)
}
View Code

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)
}
View Code

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)
}
View Code

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)
}
View Code

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

相關文章
相關標籤/搜索