Go語言基礎學習七-指針與切片操作

Go語言基礎學習七-指針與切片操作

    一.值,指針和引用類型

        與C和C++不同 Go語言中的數組是按值傳遞的,所以傳遞一個大數組的代價特別大,幸運的是,在Go語言中不常用數組,因爲我們可以用切片代替(所以切片和數組到底有什麼區別?)

        當一個變量傳入函數時,會複製該變量的值到該函數作用域,所以本地變量在不使用時會自動被垃圾回收,很多情況下我們希望自己來管理變量的生命週期而非由它的作用域決定。所以通過使用指針,我們可以讓參數的傳遞成本最低,且內容可修改,且變量的生命週期獨立於作用域。

        指針的操作與C類似,&用作取址操作,*用於取值操作指針在這裏的操作以及與++,--的優先級同C中的指針部分相似,所以這裏我就不細講了。

         Go語言的自動內存管理機制使得使用取址操作符&來取得函數參數或本地變量的地址非常安全,因爲Go語言中只要一個指針引用一個變量那個變量就會在內存中保留。若在C及C++中這麼操作非靜態變量將會非常麻煩!(費解?有待考慮)

         在一些場景,我們需要傳遞非引用類型的可修改值,或需要高效的傳入大類型的值,這時候需要使用到指針,Go語言提供了兩種,創建變量的語法,同時獲得指向它們的指針:

            1.使用內置的new()函數

            2.使用地址操作符。

          如: type composer struct{

                   name   string

                   birthYear int

                }

一些初始化方法

         1.  antony := composer{“antony davis”,1994}

         2. antopoint := new (compser)

              antopoint.name,antopoint. birthYear = “antony”,1994

         3. antopoint :=&composer{}

              antopoint.name,antopoint. birthYear = “antony”,1994

         4. antopoint :=&composer{“antony”,1994}

               

               fmt.Println(antony)-> {“antony davis”,1994}輸出結構體值

               fmt.Println(antopoint)-> &{“antony”,1994}輸出結構體值前面加一個&表示該變量是指針類型

            new(Type) = &Type{}均分配了Type類型的空值同時返回指向該值的指針,並且該值的生命週期會被Go語言的內存管理系統打理(感覺Go的內存管理系統真是牛逼,什麼都做!)

           切片和映射都是引用類型(之後解釋,還包括通道,函數,方法),保存引用類型的變量非常廉價(64位機器上,一個切片佔16字節,一個映射佔8字節)。其使用語法與變量值一樣。所以當我們需要傳遞大量值的情況下,使用切片來傳遞,若這些值各異,使用一個指向結構體的指針。

            fun inflate(numbers []int,factor int){//s使用切片作爲參數,可以直接對該切片指向的值進行修改。

               for i:=range numbers{//沒有使用for i,number := range numbers然後對number進行操作,因爲這樣得到的number是複製的值,不能直接作用於numbers,使得修改無效。

                   numbers[i] *=factor 

                   }

              }

         二 數組和切片的區別:

             數組是一個定長的序列,數組在初始化的過程中對長度就已經設定,數組的長度都是固定的並且不可修改的,所以數組的容量cap()和長度len()相等如:

              [length]Type

                [N] Type{value1,value2,value3…,valueN}

                […] Type{value1,value2,value3…,valueN}//[]內使用...操作符表示自動計算數組的長度。

             而切片是一個容量固定,長度可變的相同類型元素的序列,容量就是指最多能裝下數據的個數,長度則是實際裝下數據的個數。但是切片的容量還可以通過append()函數來增長,切片的初始化如下:

                make([]Type,length,capacity)//馬克用於創建切片,映射和通道

                make([]Type,length)

                []Type{}

                []Type{value1,value2,value3…,valueN}//[]內爲空即是切片

             一些常用的切片操作(數組和切片均可以採用這些操作來進行切片):s[n],s[n:m],s[n:],s[:m],s[:](從切片索引0到len(s)-1所獲得得切片),s[:cap(s)](增加切片的長度到切片的容量)

        三  索引與分割切片

             一個切片是一個隱藏數組的引用(這裏對引用的概念還是很模糊),對於該切片的切片也是引用於同一數組,所以只要對該數組的切片進行修改,該數組就會被修改且直接影響其它切片。

                結構體指針切片的使用:

                type Product struct{

                       name string

                       price float64

                  }

                products:=[]*Product{{“Dennis”,49},{“Box”,90}}//product爲結構體指針切片

                for _,product :=range products{

                          product.price+=0.50//這裏的修改直接作用於原結構體數據,因爲該for range複製的product是一個指向結構體的指針,直接作用於該結構體

                      }

         四   切片的修改

                1.如果我們需要往切片末尾中追加元素,可以使用內置的append()函數。如果我們向向該切片中追加另一個切片,我們必須使用...操作符來告訴Go語言把被添加進來的切片當成多個元素

                s = append(s,”h”,”i”,”j”)//添加多個單一的值

                s = append(s,t…)//添加切片t中的所有值

                s = append(s,u[2:5]…)//添加一個子切片中的所有元素

                b = append(b,letters…)//b爲一個字節切片,letters爲字符串,將一個字符串字節添加進一個字節切片中去。

               2.如果我們想要在切片的指定位置插入元素,可使用InsertStringSliceCopy()函數

                s:=[]string{“M”,”N”,”S”,”T”}

                x:=InsertStringSliceCopy(s,[]string{“a”,”b”,”c”},0)在開頭插入切片,0爲插入位置,當0改爲len(s)則是在末尾插入切片。

               3.如果我們想要複製切片中的內容,可以使用copy()函數

                copy(slicetarget,slicesource)將源切片中的內容複製到目標切片中去,返回所複製元素的個數,如果目標切片的長度不夠來容納源切片中的項,則無法容納的部分將會被忽略

               4.相對於InsertStringSliceCopy還有一個切片插入函數InserStringSlice()使用方法與InsertStringSliceCopy一樣,但是InserStringSlice會修改原始切片,並不是得到一個插入後的全新切片,而是直接在原切片上修改。

               5.切片的刪除操作非常簡單,使用相應的切片操作即可如:s = s[2:]//刪除0~1頭部元素,s = s[:5]//刪除索引爲5以後的尾部元素  ,s=append(s[:1],s[5:])//從中間刪除s[1:5],若想要不改變原始切片可以使用RemoveStringSliceCopy(s,start,end),s爲切片,start爲起始索引,end爲結束索引,同理對應的直接修改切片的函數爲RemoveStringSlice(s,start,end)

               6.對切片的搜索排序


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章