Go語言 基本類型


在內存中的形式

首先看一下在go中,一些基礎類型在內存中是以什么形態存在的,如下圖所示:

基礎類型在內存中的存在形式

變量j的類型是int32, 而變量i的類型是int,兩者不是同一個類型,所以賦值操作i=j是一種類型錯誤cannot use j (type int32) as type int in assignment

正確的方式應該是

	i := int(7) j := int32(7) i = int(j)

結構體的域在內存中是緊密排列的。

靜態類型和底層類型

byte是Go的靜態類型,uint8是Go的底層類型

rune是int32的別名,用於表示unicode字符。通常在處理中文的時候需要用到它

string類型

定義在go-1.8.3/go/src/runtime/string.go

type stringStruct struct { str unsafe.Pointer len int }

兩個屬性:一個指針,一個int型的長度,都是私有成員!

go對string類型的定義

string類型類型在Go語言的內存模型中用一個2字長的數據結構表示。 從上圖可以看出,其實多個string是共享一個存儲的。

str[i:j]進行字符串切片操作,會得到一個新的type stringStruct struct對象,該對象的指針依然還是指向str的底層存儲,長度為j-i。 這說明字符串切分不涉及內存分配或復制操作,其效率等同於傳遞下標。

內建函數len()對string類型的操作是直接從底層結構中取出len值,而不需要額外的操作

slice類型

定義在/go-1.8.3/src/runtime/slice.go

type slice struct { array unsafe.Pointer len int cap int }

顯然,type slice struct和上面的type stringStruct struct很類似,只是多了一個cap屬性。

slice的定義

一個slice是一個底層數組的部分引用。同理,對底層數據進行切片操作也不會涉及到內存分配或復制操作,僅僅是新建了一個type slice struct對象而已!

需要注意的是,在上圖中,y[0:4]是有效的,打印出來的結果會是[3,5,7,11]

由於slice是不同於指針的多字長結構,分割操作並不需要分配內存,甚至沒有通常被保存在堆中的slice頭部。這種表示方法使slice操作和在C中傳遞指針、長度對一樣廉價。

slice相關的函數有如下幾個,是不是感覺很熟悉。

func makeslice(et *_type, len64, cap64 int64) slice func growslice(et *_type, old slice, cap int) slice func slicecopy(to, fm slice, width uintptr) int func slicestringcopy(to []byte, fm string) int 

slice的擴容

對slice進行append操作時,可能會造成擴容操作。擴容規則如下:

  • 如果新的大小是當前大小2倍以上,則大小增長為新大小
  • 否則循環以下操作:如果當前長度len小於1024,按每次2倍增長,否則每次按當前cap的1/4增長。直到增長的大小超過或等於新大小。
	newcap := old.cap doublecap := newcap + newcap //和old.cap的double進行比較 if cap > doublecap { newcap = cap } else { if old.len < 1024 { newcap = doublecap } else { for newcap < cap { newcap += newcap / 4 } } }

slice與unsafe.Pointer相互轉換

  1. 利用make+slice弄塊內存出來自己管理。。。。這個比較牛逼了
s := make([]byte, 200) ptr := unsafe.Pointer(&s[0])
  1. 基於內存指針ptr構造出一個slice
var o []byte sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&o))) sliceHeader.Cap = length sliceHeader.Len = length sliceHeader.Data = uintptr(ptr)

new和make

了解完Go對type slice struct的定義之后,再來理解new和make的差異就簡單得多了。

  • new(T),僅分配內存,不進行初始化。返回的*T指向一個類型T的零值。
  • make(T, args),分配內存,且進行初始化。返回是T本身。因為T本身就是一個引用類型。

以下屬聲明的類型為例子,分別用new和make的效果如下圖:

type Point struct { X, Y int } type Rect1 struct { Min, Max Point } type Rect2 struct { Min, Max *Point }

new和make的區別

 

原文: https://github.com/Kevin-fqh/learning-k8s-source-code/blob/master/%E6%B7%B1%E5%85%A5go/(01)%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B.md


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM