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

相关文章
相关标签/搜索