GO-指針與函數

1、指針類型golang

一、普通類型,變量存的就是值,也叫值類型。指針類型存的是地址數據庫

二、獲取變量的地址,用&,好比:var a int, 獲取a的地址 &a數組

三、指針類型,變量存的是一個地址,這個地址存的纔是值閉包

四、獲取指針類型所指向的值,使用:* ,好比:var p *int,使用*p獲取p指向的變量的值app

var a int = 5 函數

var p *int = &a   0xefefefe 指向變量a的值是 5性能

五、指針類型的變量初始話有兩種:設計

5.一、直接給指針賦值其餘變量的地址指針

func test3(){
    var p *int  //默認初始化nil
    var a int
    p = &a
    *p = 200
    fmt.Println(a)
}

5.二、使用new分配對象

func test4(){
    var p *int
    p = new(int)
    *p = 2000
    fmt.Println(*p)
}

六、練習題

6.一、練習1:寫一個程序,獲取一個變量的地址,並打印到終端

package main
import (
    "fmt"
)
func test1(){
    var a int = 5
    var p *int = &a
    fmt.Printf("a的地址是:%p\n",p)
    fmt.Printf("a的值是:%d",*p)
}
func main(){
    test1()
}
運行打印的結果以下:

6.二、練習2:寫一個函數,傳入一個int類型的指針,並在函數中修改所指向的值

 

func modify(x *int){         //傳入的變量x類型是指針 *int表明指針是整形的指針
    *x = 200                      //給x指針指向的值從新賦值爲200
}
func test2(){
    var a int = 5             //定義一個整形的變量a,初始值是5
    var p *int = &a           //定義一個指針p,指向的是a
    fmt.Println("變量a的初始值是",a)   //打印a的初始值
    modify(p)                  //修改p指針指向的a的值
    fmt.Println("p指針指向的a變量的改變值是",a)   //打印a的值改變的結果

}
func main(){
    test2()
}
 
執行打印的結果以下:

 

2、內置函數

一、close:主要用來關閉channel

二、len:用來求長度,好比string、array、slice、map、channel

三、new:用來分配內存,主要用來分配值類型,好比int、struct。返回的是指針。示例能夠看上面一的5.2,

四、make:用來分配內存,主要用來分配引用類型,好比channel、map、slice

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

六、panic和recover:用來作錯誤處理

七、new和make的區別

7.一、內建函數 new 用來分配內存,它的第一個參數是一個類型,不是一個值,它的返回值是一個指向新分配類型零值的指針

7.二、內建函數 make 用來爲 slice,map 或 chan 類型分配內存和初始化一個對象(注意:只能用在這三種類型上),跟 new 相似,第一個參數也是一個類型而不是一個值,跟 new 不一樣的是,make 返回類型的引用而不是指針,而返回值也依賴於具體傳入的類型,具體說明以下:

   Slice: 第二個參數 size 指定了它的長度,它的容量和長度相同。
你能夠傳入第三個參數來指定不一樣的容量值,但必須不能比長度值小。
好比 make([]int, 0, 10)

  Map: 根據 size 大小來初始化分配內存,不過度配後的 map 長度爲 0,若是 size 被忽略了,那麼會在初始化分配內存時分配一個小尺寸的內存

  Channel: 管道緩衝區依據緩衝區容量被初始化。若是容量爲 0 或者忽略容量,管道是沒有緩衝區的

7.三、總結:

  new 的做用是初始化一個指向類型的指針(*T),make 的做用是爲 slice,map 或 chan 初始化並返回引用(T)。

3、函數

一、聲明語法:func 函數名(參數列表)[(返回值列表)]{}

  func add(){

  }

  func add(a int,b int){

  }

  func add(a int, b int) int {

  }

  func add(a int, b int) (int , int){

  }

  func add(a , b int) (int , int){

  }

二、golang函數的特色:

  a、不支持重載,一個包不能有兩個名字同樣的函數;

  b、函數是一等公民,函數也是一種類型,函數也能夠賦值給變量

  c、匿名函數

  d、多返回值

  示例: 

  type add_func func(int, int)int

  func oprator(op add_func,a int,b int)int {
      //使用傳進來的函數op,進行操做
      return op(a,b)
  }
  func add(a,b int) int {
      return a + b
  }  
  func main(){
      c:=add
      fmt.Println(c)
      sum := oprator(c,100,200)
      fmt.Println(sum)
 
  }
三、函數參數傳遞方式:
  3.一、值傳遞
  3.二、引用傳遞
  注意1:不管是值傳遞,仍是引用傳遞,傳遞給函數的都是變量的副本。值傳遞是值的拷貝,通常來講地址拷貝更高效。值拷貝取決於拷貝的對象的大小,對象越大,性能越低。
  注意2:map、slice、channel、指針、interface默認以引用的方式傳遞
四、命名返回值的名字
//重命名一個返回值
func reduce(a , b int)(c int){
    c = a - b
    return
}
//重命名多個返回值
func calc(a,b int)(sum int,avg int){
    sum = a + b
    avg = sum/2
    return
}
// _ 忽略返回值
func main(){
    sum,_ := calc(100,200)
}
五、可變參數:
多個參數
func test11(arg...int) int{
}
一個或多個參數
func test11(a int ,arg...int) int{
}
二個或多個參數
func test11(a int,b int ,arg...int) int{
}

注意:其中arg是一個slice,咱們能夠經過arg[index]來獲取多個參數

經過len(arg)來判斷傳遞參數的個數

六、練習題示例

package main

import (
    "fmt"
)

//練習題一:寫一個函數add,支持1個或多個int相加,並返回結果
func add(a int,arg...int)int{
    var sum int
    //當只有一個參數時
    if len(arg)==0{
        sum = a
    }
    //當參數大於一個時
    if len(arg)>0{
        for i:=0;i<len(arg);i++{
            //注意這裏但arg裏面只有一個參數時,i是等於0即arg[0]
            if i == 0 {
                sum = a + arg[0]
            }
            //當arg參數大於一個時
            if i >0 {
                sum+=arg[i]
            }
        }
    }
    return sum
}

//練習題二:寫一個函數concat,支持1個或多個string相拼接,並返回結果
func concat(a string,arg...string)string{
    var str string
    if len(arg)==0{
        str = a
    }
    if len(arg)>0{
        for i:=0;i<len(arg);i++{
            if i == 0 {
                str = a + arg[0]
            }
            if i >0 {
                str+=arg[i]
            }
        }
    }
    return str
}


func main(){
    fmt.Println(add(-22,23,555))
    fmt.Println(concat("aaa","bbbbb","ccccccc"))
}
 
七、defer的特色和用途
7.一、當函數返回時,執行defer語句。所以能夠用來作資源清理
7.二、多個defer語句,按先進後出的方式執行
示例:
func a(){
    fmt.Println("defer from a")
    i:=0
    defer fmt.Println(i)   //defer語句中的變量,在defer聲明時就決定
    i++ 
}
func f(){
    fmt.Println("defer from f")
    for i:=0;i<5;i++{
        defer fmt.Println(i)
    }   
}

func main(){
    //練習三
    a()
    f()
}
打印的結果:
7.三、defer語句中的變量,在defer聲明時就決定了
7.四、defer用途:關閉文件句柄,鎖資源釋放,數據庫鏈接釋放
 
4、遞歸函數
一、一個函數調用本身,就叫遞歸函數
二、斐波那契數
//斐波那契數列示例:
func fb( n int)int{
    if n <=1{
        return 1
    }
    return fb(n-1)+fb(n-2)
}
func main(){
    for i:=0;i<10;i++{
        n := fb(i)
        fmt.Println(n)
    }
}
三、遞歸的設計原則
3.一、一個大問題可以分解成類似的小問題
3.二、定義好出口條件(即結束遞歸循環的條件)
 
5、閉包
一個函數和與其相關的引用環境的組合成的實體
//示例一:
func Adder() func(int)int{
    var x int
    return func(delta int)int{
        x +=delta
        return x
    }
}
//示例2:
func makeSuffixFunc(suffix string) func(string)string{
    return func(name string)string{
        if !strings.HasSuffix(name ,suffix){
            return name + suffix
        }
        return name
    }
}
func main(){
    //練習五:閉包
    //示例1:
    // var f = Adder()
    // fmt.Println(f(1))
    // fmt.Println(f(10))
    // fmt.Println(f(100))
    //示例2:
    func1 := makeSuffixFunc(".jpg")
    func2 := makeSuffixFunc(".txt")
    fmt.Println(func1(func1("test")))
    fmt.Println(func2("test"))
}
 
6、數組和切片
1.一、排序和查找操做
  排序操做主要都在sort包中,導入就可使用
  sort.Ints對整數進行排序, sort.Strings對字符串串進⾏行行排序, sort.Float64s對 浮點數進⾏行行排序.
  sort.SearchInts(a []int, b int) 從數組a中查找b,前提是a 必須有序
   sort.SearchFloats(a []float64, b float64) 從數組a中查找b,前提是a 必須有序
  sort.SearchStrings(a []string, b string) 從數組a中查找b,前提是a 必須有序
相關文章
相關標籤/搜索