1.介紹
golang分配內存主要有內置函數new和make
相同點:
- 他們的第一個參數都是一個類型而不是一個值
不同點:
- new可分配任意類型的數據
- make只能為slice, map, channel分配內存
- new返回的是指針
- make返回類型的是引用而不是指針,并且返回的值也依賴于具體傳入的類型,
這種不同點的原因是:這三種類型(slice, map, channel)的數據結構必須在使用前初始化
func make(t Type,size IntegerType) Typemake(Type, len, cap)
- Type:數據類型,必要參數,Type 的值只能是 slice、 map、 channel 這三種數據類型。
- len:數據類型實際占用的內存空間長度,map、 channel 是可選參數,slice 是必要參數。
- cap:為數據類型提前預留的內存空間長度,可選參數,所謂的提前預留是當前為數據類型申請內存空間的時候,提前申請好額外的內存空間,這樣可以避免二次分配內存帶來的開銷,大大提高程序的性能
2.用法
- make(map[string]string)
- 缺少長度的參數,只傳類型,這種用法只能用在類型為map或chan的場景,例如make([]int)是會報錯的。這樣返回的空間長度都是默認為0的
- make([]int, 2)
- 指定了長度,例如make([]int, 2)返回的是一個長度為2的slice
- make([]int, 2, 4)
- 第二參數指定的是切片的長度,第三個參數是用來指定預留的空間長度,例如a := make([]int, 2, 4), 這里值得注意的是返回的切片a的總長度是4,預留的意思并不是另外多出來4的長度,其實是包含了前面2個已經切片的個數的。所以舉個例子當你這樣用的時候 a := make([]int, 4, 2),就會報語法錯誤
思考一個問題:為什么要指定預留的大小呢?
????????這是因為?
make()
?使用的是一種動態數組算法,一開始先向操作系統申請一小塊內存,這個就是?cap
,等?cap
?被?len
?占用滿以后就需要擴容,擴容就是動態數組再去向操作系統申請當前長度的兩倍的內存,然后將舊數據復制到新內存空間中?,一般動態數組每次擴容都是原來的兩倍,那么再來思考一個問題: 動態數組會一直這樣擴容下去嗎?????????理論上擴容應該是呈指數增長,但不同的程序員對擴容多少的理解是不一樣的,不同的語言也有不同的算法,不過最后肯定在擴容 n 次后就不能按照倍數來擴了,這是因為有物理內存的限制,避免一次申請過多從而導致內存申請失敗和內存浪費的情況
案例演示:
package mainimport "fmt"func main() {//分配片結構;* p==零var p *[]int = new([]int)*p = make([]int, 100, 100) //這樣寫有點復雜,很容易就搞亂了fmt.Println(p)//現在將V分配一個新的數組,100個整型//寫法一//var v? []int = make([]int, 100)//寫法二:非常常用的寫法,簡節明了v := make([]int, 100)fmt.Println(v)}通過make()還可以靈活地創建數組切片。如 //創建切片也使用make函數,它被分配一個零數組和指向這個數組的切片。//創建一個初始元素個數為5的數組切片,元素初始值為0a := make([]int, 5)? // len(a)=5//切片有長度和容量。切片的最大長度就是它的容量。//指定一個切片的容量,通過第三個參數。//創建一個初始元素個數為5的數組切片,元素初始值為0,并預留10個元素的存儲空間b := make([]int, 5, 10)?? ?// len(b)=5, cap(b)=10//通過重新切片,可使切片增加。b = b[:cap(b)] // len(b)=5, cap(b)=5b = b[1:]????? // len(b)=4, cap(b)=4//直接創建并初始化包含5個元素的數組切片c := []int{1,2,3,4,5}
用法:
????????[go學習筆記.第七章.數組和切片] 4.切片的三種使用方式以及注意事項和使用細節?
? ? ? ? [go學習筆記.第九章.map] 1.map的介紹,聲明,使用方式,crud操作以及遍歷
????????[go學習筆記.第十四章.協程和管道] 2.管道
3.總結
- make僅用來分配及初始化類型為 slice、map、chan 的數據,new 可分配任意類型的數據
- new分配返回的是指針,即類型 *Type,make 返回引用,即Type
- new分配的空間被清零, make 分配空間后,會進行初始化?