網站首頁 編程語言 正文
new和make
new
// The new built-in function allocates memory. The first argument // is a type,not a value, and the value returned is a pointer to a // newly // allocated zero value of that type. func new(Type) *Type
對于官方是這么解釋new
的:這個內置函數功能是分配內存。第一個參數是一個自定義類型,并不是一個值,返回值為一個指向新分配好的內存空間的一個指定類型指針,并且這個內存空間會被清零(也就是變為該類型的零值)。
使用new初始化
至于使用new
進行初始化,根據語言規范:The built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values.
因為go中的函數不能被重載,并且這不是可變參數,所以無法傳遞任何初始化數據。 取而代之的是,go將使用對類型和任何成員字段適當的任何0版本進行初始化。
零值
go語言總共分為四大類型:基本數據類型、復雜數據類型、引用數據類型和接口類型。零值是指基本數據類型和指針的初始值。
數值型零值為0
、string的零值為""
、bool的零值為false
、指針的零值為nil
。
使用示例(new也可以為數組分配內存)
a := new(int) fmt.Printf("類型為:%T, 值為:%v\n", a, a) fmt.Printf("類型為:%T, 值為:%v\n", *a, *a) b := new(string) fmt.Printf("類型為:%T, 值為:%v\n", b, b) fmt.Printf("類型為:%T, 值為:%v\n", *b, *b) c := new(*int) fmt.Printf("類型為:%T, 值為:%v\n", c, c) fmt.Printf("類型為:%T, 值為:%v\n", *c, *c) 運行結果: 類型為:*int, 值為:0xc0000a6058 類型為:int, 值為:0 類型為:*string, 值為:0xc000088220 類型為:string, 值為: 類型為:**int, 值為:0xc0000ca020 類型為:*int, 值為:<nil>
new(struct)和&struct{}區別
因為struct{}
這種操作可以對類型進行初始化,并且基于上述new的理解之后就會發現&struct{}
和new(struct)
其實這兩種聲明方式幾乎沒有區別。但我們在項目中經常會使用到這兩種操作,就自然會想這兩者的區別(跟本人一樣)。
在我調查了一些資料后,我個人覺得他們唯一的區別就在于new
只能聲明一個零值的該類型的指針并返回,但是&struct{}
可以在聲明的同時進行初始化操作。
func main(){ A := new(struct) // 只能返回一個struct的指針 B := &struct{Id:1,Name:"張三"} // 可以返回一個帶有默認值的struct的指針 }
上述例子就很好的說明了這個問題。
小結
new
只能開辟單個空間,不能為引用類型開辟多個空間。并且new
是對類型進行內存的開辟,返回一個指向該內存空間的指針類型。如果使用new
去初始化引用數據類型,不是很合適(當然,new
一個對象還是可以的)。因此就需要用到另一個內置函數make。
make
// The make built-in function allocates and initializes an object of type // slice, map, or chan (only). Like new, the first argument is a type, not a // value. Unlike new, make's return type is the same as the type of its // argument, not a pointer to it. The specification of the result depends on // the type: func make(t Type, size ...IntegerType) Type
對于官方是這么解釋make
的:該函數功能是分配內存并且初始化一個切片(slice/map/channel)
類型的對象。相比較內置函數new
而言,make
的第一個參數也是一個自定義類型,不是一個值。但make
的返回類型是一個和他傳入的自定義參數類型完全相同的類型。并不是一個指針去指向這個新開辟的內存空間。
make
也是用于內存分配的,但是和 new
不同,它只用于 chan、map
以及 slice
的內存創建,而且它返回的類型就是這三個類型本身,而不是他們的指針類型,因為這三種類型就是引用類型,所以就沒有必要返回他們的指針了。
簡述make的初始化(slice/map/channel)
make
在對slice/map/channel
這三種類型進行初始化時,在編譯初期階段,go語言就已經將代表make
關鍵字的OMAKE
節點根據參數類型的不同轉換成了OMAKESLICE、OMAKEMAP、OMAKECHAN
三種不同類型的節點。這些不同的節點最終會調用不同的運行時函數來初始化數據結構。
使用示例
var a []int fmt.Println(a[0]) // 運行結果 panic: runtime error: index out of range [0] with length 0
如果不對切片進行初始化,就無法使用
var a []int a = make([]int, 1) fmt.Println(a[0])
map
和chan
也同理。切片需要指定長度大小,容量可以自動擴容。如果下標超出指定的長度也會出現數組越界的情況。但是map
不會發生該情況。即使初始化map
容量為0
,map
底層也會自動進行擴容。對于channel
來說初始化容量就是初始化緩沖區長度。
總結:
make
和new
共同點都是可以開辟內存空間,給變量分配內存。
不同點在于:
- 兩者的作用類型不同,
new
給int、string、數組
分配內存,make
給slice、map、channel
分配內存。 - 兩者的返回值不同,
new
的返回值類型為一個指向新分配好的內存空間的一個指定類型指針。而make
的返回值類型為它本身。 -
new
分配的內存空間會被清零。make
分配空間之后會被初始化。 -
new分配的內存空間不一定會在堆上分配,當指向這個內存空間的指針變量作用域不會在作用域外被使用,或者說這個變量只使用一次就不再使用。那么
new
分配的內存空間就會在當前的函數棧中隨著棧的結束而被銷毀。make則會在棧上開辟一塊棧幀,棧幀里面有棧的指針和棧頂指針,分別記錄棧幀的空間,隨著函數的執行完畢,棧里的棧幀就會自動清空。
簡單的說,new
只分配內存,make
用于slice,map,和channel
的初始化,并且不返回指針。要獲得一個顯式的指針,使用new
進行分配,或者顯式地使用一個變量的地址。
參考資料
go語言中文網
深入學習golang
原文鏈接:https://blog.csdn.net/cczj0/article/details/128636169
相關推薦
- 2022-08-27 如何利用Pandas查詢選取數據_python
- 2022-09-14 Python實現刪除windows下的長路徑文件_python
- 2022-10-20 Kotlin作用域函數應用詳細介紹_Android
- 2022-11-08 C/C++實現遍歷文件夾最全方法總結_C 語言
- 2022-09-30 關于react中useCallback的用法_React
- 2023-12-13 python處理Excel文檔(一)合并Excel工作表
- 2022-07-27 C++中整形與浮點型如何在內存中的存儲詳解_C 語言
- 2022-08-16 C語言清楚了解指針的使用_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支