Go中的new()和make()函數(shù)區(qū)別及底層原理詳解
引言
在 Go 語言中,new()
和 make()
是兩個常用的函數(shù),用于創(chuàng)建和初始化不同類型的變量。本文將深入探討 new()
和 make()
的區(qū)別、使用場景以及底層實現(xiàn)原理。
- Go 中的
new()
和make()
函數(shù)是用于創(chuàng)建和初始化變量的重要工具。 new()
用于創(chuàng)建指定類型的零值變量,并返回該變量的指針。make()
用于創(chuàng)建并初始化引用類型的變量,如切片、映射和通道。
new() 函數(shù)
new()
函數(shù)的基本語法及用法。new()
創(chuàng)建的變量是指定類型的零值,并返回該變量的指針。new()
適用于創(chuàng)建引用類型以外的其他類型變量。
package main import "fmt" func main() { // 使用 new() 創(chuàng)建一個 int 類型的零值變量的指針 numPtr := new(int) fmt.Println(*numPtr) // 輸出 0 }
make() 函數(shù)
make()
函數(shù)的基本語法及用法。make()
用于創(chuàng)建并初始化引用類型的變量。make()
適用于創(chuàng)建切片、映射和通道等引用類型的變量。make()
創(chuàng)建的變量不是零值,而是根據(jù)類型進行初始化。
package main import "fmt" func main() { // 使用 make() 創(chuàng)建一個切片,并初始化長度為 3 的切片 slice := make([]int, 3) fmt.Println(slice) // 輸出 [0 0 0] }
new() 和 make() 的區(qū)別
new()
用于創(chuàng)建任意類型的變量,而make()
僅用于創(chuàng)建引用類型的變量。new()
返回的是指針,而make()
返回的是初始化后的值。new()
創(chuàng)建的變量是零值,make()
創(chuàng)建的變量是根據(jù)類型進行初始化。
package main import "fmt" func main() { // 使用 new() 創(chuàng)建一個結構體的指針 personPtr := new(Person) personPtr.Name = "Alice" personPtr.Age = 30 fmt.Println(personPtr) // 輸出 &{Alice 30} // 使用 make() 創(chuàng)建一個映射,并初始化鍵值對 m := make(map[string]int) m["one"] = 1 m["two"] = 2 fmt.Println(m) // 輸出 map[one:1 two:2] } type Person struct { Name string Age int }
new() 和 make() 的底層實現(xiàn)原理
在 Go 語言中,new()
和 make()
的底層實現(xiàn)原理略有不同。
new()
的底層實現(xiàn)原理
new()
函數(shù)在底層使用了 Go 的runtime.newobject
函數(shù)。runtime.newobject
函數(shù)會分配一塊內存,大小為指定類型的大小,并將該內存清零。- 然后,
runtime.newobject
函數(shù)會返回這塊內存的指針。
下面是 new()
函數(shù)的簡化版本的底層實現(xiàn)原理示例代碼:
package main import ( "fmt" "unsafe" ) func main() { // 使用 new() 創(chuàng)建一個 int 類型的零值變量的指針 numPtr := new(int) // 獲得指針的值 ptrValue := uintptr(unsafe.Pointer(numPtr)) // 輸出指針的值 fmt.Println(ptrValue) }
在上述示例代碼中,我們使用了 unsafe
包中的 Pointer
和 uintptr
類型來操作指針。我們首先使用 new(int)
創(chuàng)建一個 int 類型的零值變量的指針 numPtr
,然后通過 unsafe.Pointer
將指針轉換為 unsafe.Pointer
類型,再通過 uintptr
將 unsafe.Pointer
值轉換為 uintptr
類型,最后輸出指針的值。這個值就是我們所創(chuàng)建的變量的內存地址。
make() 的底層實現(xiàn)原理
make()
函數(shù)在底層使用了 Go 的runtime.makeslice
、runtime.makemap
和runtime.makechan
函數(shù)。runtime.makeslice
函數(shù)用于創(chuàng)建切片,它會分配一塊連續(xù)的內存空間,并返回切片結構體。runtime.makemap
函數(shù)用于創(chuàng)建映射,它會分配一塊哈希表內存,并返回映射結構體。runtime.makechan
函數(shù)用于創(chuàng)建通道,它會分配一塊通道內存,并返回通道結構體。
下面是 make()
函數(shù)的簡化版本的底層實現(xiàn)原理示例代碼:
package main import ( "fmt" "reflect" "unsafe" ) func main() { // 使用 make() 創(chuàng)建一個切片,并初始化長度為 3 的切片 slice := make([]int, 3) // 獲得切片的值和長度 sliceValue := reflect.ValueOf(slice) sliceData := sliceValue.Elem().UnsafeAddr() sliceLen := sliceValue.Len() // 輸出切片的值和長度 fmt.Println(sliceData, sliceLen) }
在上述示例代碼中,我們使用了 reflect
包中的 Value
、Elem
和 UnsafeAddr
方法來操作切片。我們首先使用 make([]int, 3)
創(chuàng)建一個長度為 3 的切片 slice
,然后通過 reflect.ValueOf
將切片轉換為 reflect.Value
類型,再通過 Elem
方法獲取切片的元素,并通過 UnsafeAddr
方法獲取切片的底層數(shù)組的指針,最后通過 Len
方法獲取切片的長度。這樣,我們就可以獲得切片的底層數(shù)組的指針和長度。
請注意,上述示例代碼中使用了 reflect
和 unsafe
包,這是為了演示 make()
的底層實現(xiàn)原理而引入的,實際開發(fā)中并不需要經常使用這些包。
總結
通過深入了解 new()
和 make()
函數(shù)的區(qū)別、使用場景以及底層實現(xiàn)原理,讀者可以更好地理解和運用這兩個函數(shù),并完美解決掉面試官的問題,并在實際開發(fā)中做出準確的選擇。
以上就是Go中的new()和make()函數(shù)區(qū)別及底層原理詳解的詳細內容,更多關于Go new make函數(shù)的資料請關注腳本之家其它相關文章!
相關文章
詳解Golang time包中的結構體time.Ticker
在日常開發(fā)過程中,會頻繁遇到對時間進行操作的場景,使用 Golang 中的 time 包可以很方便地實現(xiàn)對時間的相關操作,接下來的幾篇文章會詳細講解 time 包,本文講解一下 time 包中的結構體 time.Ticker,需要的朋友可以參考下2023-08-08基于Go語言實現(xiàn)高性能文件上傳下載系統(tǒng)
在Web應用開發(fā)中,文件上傳下載是一個非常常見的需求,本文將介紹如何使用Go語言實現(xiàn)一個安全、高效的本地文件存儲系統(tǒng),感興趣的小伙伴可以了解下2025-03-03