Go語言學習13-內建函數

內建函數

所謂內建函數,就是Go語言內部預約義的函數。調用它們的方式與調用普通函數並沒有差別,而且在使用它們以前也不須要導入任何代碼包。這裏並不能把內建函數當作值來使用。由於它們並不像普通函數那樣有隸屬的Go語言數據類型。數組

1. close函數

內建函數 close 只接受通道類型的值(簡稱通道)做爲參數。例如:數據結構

ch := make(chan int, 1)
close(ch)

調用這個 close 函數以後,會使做爲參數的通道沒法再接受任何元素值。若試圖關閉一個僅能接受元素值的通道,則會形成一個編譯錯誤。在通道被關閉以後,再向它發送元素值或者試圖再次關閉它的時候,都會引起一個運行時恐慌。試圖關閉一個爲 nil 的通道值也會引起一個運行時恐慌。app

試圖調用 close 函數關閉一個通道,並不會影響到在此調用以前已經發送的那些元素值,它們會被正常接收(若是存在接收操做的話)。可是,在此調用以後,全部的接收操做都會當即返回一個該通道的元素類型的零值。ide

2. len函數與cap函數

2.1 len函數的使用方法

參數類型 結果 備註
string string類型值的字節長度
[n]T或*[n]T 數組類型值長度,它等於n n表明了數組類型的長度,T表明了數組類型的元素類型
[]T 切片類型值的長度 T表明了切片類型的元素類型
map[K]T 字典類型值的長度,其中已包含的鍵的數量 K表明了字典類型的鍵類型,T表明了字典類型的元素類型
chan T 通道類型值當前包含的元素的數量 T表明了通道類型的元素類型

2.2 cap函數的使用方法

參數類型 結果 備註
[n]T或*[n]T 數組類型值長度,它等於n n表明了數組類型的長度,T表明了數組類型的元素類型
[]T 切片類型值的容量 T表明了切片類型的元素類型
chan T 通道類型值的容量 T表明了通道類型的元素類型

對於一個切片類型值來講,它的長度和容量的關係:函數

0 <= len(s) <= cap(s)性能

一個切片值的容量就是它擁有的那個底層數組的長度。這個底層數組的長度一定不會小於該切片值的長度。學習

值爲 nil切片類型值字典類型通道類型值 的長度都是 0 。值爲 nil切片類型值通道類型值 的容量也都是 0.net

若是 s 是一個 string 類型的常量,那麼表達式 len(s)cap(s) 也都等同於常量。len(s) 所表明的值在編譯期間就會被計算出來。若是 s 是一個表達式,且其類型是數組類型或指向數組類型的指針類型,那麼只要該表達式中不包含通道接收操做和函數調用操做,它就不會被求值。由於 s 的類型中已經包含了它的長度信息。在對錶達式 len(s)cap(s) 進行求值的時候並不須要求得 s 的結果值而只須要從 s 的類型中取得其長度便可。在這種狀況下,這兩個表達式也會等同於常量。指針

3. new函數和make函數

這兩個函數是專門用於數據初始化。這裏的數據初始化是指對某個數據類型的值或變量的初始化。在Go語言中,幾乎全部的數據類型的值均可以使用字面量來進行表示和初始化。在大多數狀況下,使用字面量就能夠知足初始化值或變量的要求。code

3.1 new

內建函數 new 用於爲值分配內存。它並不會去初始化分配到的內存,而只會清零它。例如:

new(T)

如上調用該表達式求值時,所作的是爲 T 類型的新值分配並清零一塊內存空間,而後將這塊內存空間的地址做爲結果返回。而這個結果就是指向這個新的 T 類型值的指針值。它的類型爲 *Tnew* 函數返回的 T 類型值老是指向一個 T** 類型的零值。例如:

new(string) // 求值結果指向的是一個string類型的零值""
new([3]int) // 求值結果指向的是一個[3]int類型的零值[3]int{0,0,0}

以標準庫代碼包 bytes 中的結構體類型 Buffer 爲例, bytes.Buffer 是一個尺寸可變的字節緩衝區。它的零值就是一個當即可用的空緩衝區。例如:

// 求值結果就是一個指向一個空緩衝區的指針值,能夠當即在這個緩衝區上進行讀寫操做
new(bytes.Buffer)

標準庫代碼包 sync 中的結構體類型 Mutex 也是一個能夠 new 後即用的數據類型。它的零值就是一個處於未鎖定狀態的互斥量。

3.2 make

內建函數 make 只能被用於建立切片函數、字典類型和通道類型的值,並返回一個已被初始化的(即非零值的)的對應類型的值。以上3個複合類型的特殊結構都是引用類型,在它們的每個值的內部都會保持着一個對某個底層數據結構值的引用。若是不對它們的值進行初始化,那麼其中的這種引用關係是不會創建起來的,同時相關的內部值也會不正確。所以在建立這3個引用類型的值的時候,必須將內存空間分配和數據初始化這兩個步驟綁定在一塊兒。

內建函數 make 除了會接受一個表示目標類型的類型字面量以外,還會接受一個或兩個額外的參數。

對於切片類型來講,能夠把新值的長度和容量也傳遞給 make 函數,例如:

make([]int, 10, 100)

如上建立了一個新的 [ ]int 類型的值,這個值的長度爲 10,容量爲 100。若是省略最後一個參數,即不指定新值的容量。這樣的話,該值的容量會與其長度一致。例如:

s := make{[]int, 10}

變量 s 的類型是 [ ]int 的,而長度和容量都是 10

在使用 make 函數初始化一個切片值的過程當中,該值會引用一個長度與其容量相同且元素類型與其元素類型一致的數組值。這個數組值就是該切片值的底層數組。該數組值中每一個元素都是當前元素類型的零值。可是,切片值只會展示出數量與其長度相同的元素。所以 make([ ]int, 10, 100) 所建立並初始化的值就是 [ ]int{0,0,0,0,0,0,0,0}

在使用 make 函數建立字典類型的值的時候,也能夠指定其底層數據結果的長度。可是,該字典值只會展現出咱們明確「放入」的鍵值對。例如:

make(map[string]int, 100)

它所建立和初始化的值會使 map[string]int{}。雖然能夠忽略那個用於表示底層數據結構長度的參數,可是這邊仍是建議:應該在性能敏感的應用場景下,根據這個字典值可能包含的鍵值對的數量以及「放入」它們的時間,仔細地設置該長度參數。

對於通道類型的值的數據初始化,這裏可使用 make 函數建立一個通道類型的值:

make(chan int, 10)

其中的第一個參數表示的是通道的類型,而第二個參數則表示該通道的長度。與字典類型相同,第二個參數也能夠被忽略掉。對於忽略它的含義,在以後的博文中詳細講解通道類型的時候你們能夠了解。

內建函數 make 只能被應用在引用類型的值的建立上。而且,它的結果是第一個參數所表明的類型的值,而不是指向這個值的指針值。若是想要獲取該指針值的話,只須要以下:

m := make(map[string]int , 100)
mp := &m

對於數據初始化須要考慮的一些規則:

  1. 字面量能夠被用於初始化幾乎全部的Go語言數據類型的值,除了接口類型和通道類型。接口類型沒有值,而通道類型的值只能使用 make 函數來建立。若是須要指向值的指針值,能夠在表示該值的字面量之上進行取址操做。

  2. 內建函數 new 主要用於建立值類型的值。調用 new 函數的額表達式的結果值將會是指向被建立值的指針值,而且被建立值會是其所屬數據類型的零值。所以,new 函數不適合被用來建立引用類型的值。其直接的緣由是引用類型的值的零值都是 nil,是不可用的。

  3. 內建函數 make 僅被用於某些引用類型(切片類型、字典類型和通道類型)的指的建立。它在建立值以後還會對其進行必要的初始化。與 new 函數不一樣,調用 make 函數的表達式的結果值將會是被建立的值自己,而不是指向它的指針值。

4. append函數和copy函數

append 函數和 copy 函數都被用於輔助在切片類型值之上的操做,這部份內容參考 Go語言學習5-切片類型

5. delete函數

內建函數 delete 專用於刪除一個字典類型值中的某個鍵值對。它接受兩個參數,第一個參數是做爲目標的字典類型值,而第二個參數則是可以表明要刪除的那個鍵值對的鍵。例如:

delete(m, k)

這裏有兩點須要注意:

  • 第二個參數 km 的鍵的類型之間必須知足賦值規則。
  • m 的值是 nil 或者 k 所表明的鍵值對並不存在於 m 中的時候,delete(m, k) 不會作任何操做。在沒有可刪除的目標的時候,刪除操做將被忽略。這種刪除失敗不會被反饋。

6. complex 函數、real 函數和 imag 函數

這3個內建函數都是專用於操做複數類型值的。

complex 函數被用於根據浮點數類型的實部和虛部來構造複數類型。例如:

var cplx128 complex128 = complex(2, -2)

內建函數 realimag 則分別被用於從一個複數類型值中抽取浮點數類型的實部部分和浮點數類型的虛部部分。例如:

var im64 = imag(cplx128)
var r64 = real(cplx128)

對於 complex 函數來講,兩個參數的類型必須是同一種浮點數類型,而且其結果類型與參數類型對應。在Go語言中,對於複數有一個恆等式:

z == complex(real(z), imag(z)) // z是一個複數類型的變量

注意: 若是 complex 函數的兩個參數都沒有顯示的類型,那麼該函數的結果的類型將會是 complex128 類型的。若是 complex 函數的參數都是常量,那麼它的結果值也必是常量。

7. panic函數和recover函數

內建函數 panic 函數和 recover 函數分別被用於報告和處理運行時恐慌。

函數 panic 只接受一個參數。這個參數能夠是任意類型的值。按照慣例,panic 函數的實際參數的類型經常是接口類型 error 的某個實現類型。panic 函數的參數都應該足以表示恐慌發生時的異常狀況。

函數 recover 不接受任何參數,可是返回一個 interface{} 類型的結果值。interface{} 就是空接口。全部的數據類型都是它的實現類型。所以,recover 函數的結果值多是任何類型的。這是與 panic 函數的那個惟一參數相對應的,它們都是 interface{} 類型的。若是運行時恐慌的報告是經過調用 panic 函數來進行的話,那麼以後調用 recover 函數所得的結果值就應該是先前 panic 函數在被調用時接受的那個參數值。recover 函數的結果值也有可能 nil 。若是是 nil,屬於如下的狀況:

  • 傳遞給panic函數的參數值就是nil。
  • 運行時恐慌根本就沒有發生。狹義的講,panic函數沒有被調用。
  • 函數recover並無在defer語句中被調用。

在任何狀況下任何位置上調用 recover 函數都不會產生任何反作用。若是不用它來處理運行時恐慌,那麼對它的調用也就沒有任何意義了。panic 函數和 recover 函數之間確定是存在着某種聯繫,在後面的博文中將對異常報告和處理的更多細節進行講解。

8. print函數和println函數

函數 print 的做用是依次(即從左到右)打印出傳遞給它的參數值,每一個參數值對應的打印內容都由它們的具體實現決定。而函數 println 函數則會在 print 函數打印的內容的基礎上再在每一個參數之間加入空格,並在最後加入換行符。例如:

print("A", 12.4, 'R', "C")
println("A", 12.4, 'R', "C")

調用表達式被求值以後,出現內容:

A+1.240000e+00182CA +1.240000e+001 82 C

對於上面的這兩個函數,有如下須要注意:

  • 它們接受的參數只能是有限的數據類型的值。而且,在這些受支持的數據類型當中。大部分都是Go語言的基礎數據類型。

  • 這兩個函數針對於每種受支持的數據類型的打印格式都是固定的,沒法自定義。

Go語言並不保證會在之後的版本中一直保留這兩個函數。所以,儘可能不要在程序中使用這兩個函數,尤爲是用於生產環境的程序。應該使用標準庫代碼包 fmt 中的函數 PrintPrintln 來替代它們。

結語

至此,Go語言數據的使用 就講完了,下篇博文將要介紹 Go語言流程控制方法,敬請期待!!!

相關文章
相關標籤/搜索