目錄
new
make
小結:
首頁 後端開發 Golang go語言中make和new的差別是什麼?

go語言中make和new的差別是什麼?

Dec 09, 2020 am 10:59 AM
go語言 make new

區別:在go語言中,make和new都是記憶體的分配(堆上),但是make只用於slice、map以及channel的初始化(非零值);而new用於類型的記憶體分配,且記憶體置為零。 make回傳的是引用型別本身;而new回傳的是指向型別的指標。

go語言中make和new的差別是什麼?

本文操作環境:windows10系統、GO 1.11.2、thinkpad t480電腦。

相關推薦:《go教學

Go語言中new和make都是用來記憶體分配的原語(allocation primitives)。簡單的說,new只分配內存,make用於slice,map,和channel的初始化。

new

new(T)函數是一個分配記憶體的內建函數。

我們都知道,對於一個已經存在變量,可對其指標進行賦值。

範例

var p int
var v *int
v = &p
*v = 11
fmt.Println(*v)
登入後複製

那麼,如果不是已經存在的變數會如何呢?能對其直接賦值嗎?

範例

var v *int
*v = 8
fmt.Println(*v)
登入後複製

結果會回報如下錯誤

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pcr=0x0 pcr=0x0 =0x48df66]

如何解決?透過Go提供了new來初始化一位址就可以解決。

var v *int
v = new(int)
*v = 8
fmt.Println(*v)
登入後複製

那麼我們來分析一下

var v *int
	fmt.Println(*v)
fmt.Println(v) //<nil>
v = new(int) 
fmt.Println(*v)//
fmt.Println(v)//0xc00004c088
登入後複製

我們可以看到初始化一個指標變量,其值為nil,nil的值是不能直接賦值的。透過new其傳回指向新指派的型別為int的指針,指標值為0xc00004c088,這個指標所指向的內容的值為零(zero value)。

同時,需要注意的是不同的指標類型零值是不同的。

範例

type Name struct {
	P string
}
var av *[5]int
var iv *int
var sv *string
var tv *Name

av = new([5]int)
fmt.Println(*av) //[0 0 0 0 0 0]
iv = new(int)
fmt.Println(*iv) // 0
sv = new(string) 
fmt.Println(*sv) //
tv = new(Name)
fmt.Println(*tv) //{}
登入後複製

上面講了對普通型別new()處理過後是如何賦值的,這裡再講一下對複合型別(數組,slice,map,channel等),new( )處理過後,如何賦值。

陣列範例

	var a [5]int
	fmt.Printf("a: %p %#v \n", &a, a)//a: 0xc04200a180 [5]int{0, 0, 0, 0, 0} 
	av := new([5]int)
	fmt.Printf("av: %p %#v \n", &av, av)//av: 0xc000074018 &[5]int{0, 0, 0, 0, 0}
	(*av)[1] = 8
	fmt.Printf("av: %p %#v \n", &av, av)//av: 0xc000006028 &[5]int{0, 8, 0, 0, 0}
登入後複製

silce 範例

	var a *[]int
	fmt.Printf("a: %p %#v \n", &a, a) //a: 0xc042004028 (*[]int)(nil)
	av := new([]int)
	fmt.Printf("av: %p %#v \n", &av, av) //av: 0xc000074018 &[]int(nil)
	(*av)[0] = 8
	fmt.Printf("av: %p %#v \n", &av, av) //panic: runtime error: index out of range
登入後複製

map 範例

	var m map[string]string
	fmt.Printf("m: %p %#v \n", &m, m)//m: 0xc042068018 map[string]string(nil) 
	mv := new(map[string]string)
	fmt.Printf("mv: %p %#v \n", &mv, mv)//mv: 0xc000006028 &map[string]string(nil)
	(*mv)["a"] = "a"
	fmt.Printf("mv: %p %#v \n", &mv, mv)//这里会报错panic: assignment to entry in nil map
登入後複製

channel範例

cv := new(chan string)
fmt.Printf("cv: %p %#v \n", &cv, cv)//cv: 0xc000074018 (*chan string)(0xc000074020) 
//cv <- "good" //会报 invalid operation: cv <- "good" (send to non-chan type *chan string)
登入後複製

透過上面範例我們看到陣列通過new處理,數組av初始化零值,數組雖然是複合類型,但不是引用類型,其他silce、map、channel類型也屬於引用類型,go會給引用類型初始化為nil,nil是不能​​直接賦值的。並且不能用new分配記憶體。無法直接賦值。那麼用make函數處理會是怎麼樣呢?

make

範例

av := make([]int, 5)
fmt.Printf("av: %p %#v \n", &av, av) //av: 0xc000046400 []int{0, 0, 0, 0, 0}
av[0] = 1
fmt.Printf("av: %p %#v \n", &av, av) //av: 0xc000046400 []int{1, 0, 0, 0, 0}
mv := make(map[string]string)
fmt.Printf("mv: %p %#v \n", &mv, mv) //mv: 0xc000074020 map[string]string{}
mv["m"] = "m"
fmt.Printf("mv: %p %#v \n", &mv, mv) //mv: 0xc000074020 map[string]string{"m":"m"}
chv := make(chan string)
fmt.Printf("chv: %p %#v \n", &chv, chv) //chv: 0xc000074028 (chan string)(0xc00003e060)
go func(message string) {
   chv <- message // 存消息
}("Ping!")
fmt.Println(<-chv) // 取消息 //"Ping!"
close(chv)
登入後複製

make不僅可以開啟一個內存,還能給這個記憶體的型別初始化其零值。

它和new還能配合使用

範例

var mv *map[string]string
fmt.Printf("mv: %p %#v \n", &mv, mv)//mv: 0xc042004028 (*map[string]string)(nil) 
mv = new(map[string]string)
fmt.Printf("mv: %p %#v \n", &mv, mv)//mv: 0xc000006028 &map[string]string(nil)
(*mv) = make(map[string]string)
(*mv)["a"] = "a"
fmt.Printf("mv: %p %#v \n", &mv, mv)//mv: 0xc042004028 &map[string]string{"a":"a"}
登入後複製

透過new給指標變數mv分配了一個內存,並賦予其記憶體位址。 Map是引用型,其零值為nil,使用make初始化 map,然後變數就能使用*給指標變數mv賦值了。

小結:

  • make和new都是golang用來分配記憶體的內置函數,並且在堆上分配內存,make 即分配內存,也初始化記憶體。 new只是將記憶體清零,並沒有初始化記憶體。
  • make回傳的還是引用型別本身;而new回傳的是指向型別的指標。
  • make只能用來指派及初始化型別為slice,map,channel的資料;new可以指派任意型別的資料。

更多程式相關知識,請造訪:程式設計教學! !

以上是go語言中make和new的差別是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1267
29
C# 教程
1239
24
在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? 在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? Apr 02, 2025 pm 04:54 PM

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

GoLand中自定義結構體標籤不顯示怎麼辦? GoLand中自定義結構體標籤不顯示怎麼辦? Apr 02, 2025 pm 05:09 PM

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

Go的爬蟲Colly中Queue線程的問題是什麼? Go的爬蟲Colly中Queue線程的問題是什麼? Apr 02, 2025 pm 02:09 PM

Go爬蟲Colly中的Queue線程問題探討在使用Go語言的Colly爬蟲庫時,開發者常常會遇到關於線程和請求隊列的問題。 �...

在 Go 語言中,為什麼使用 Println 和 string() 函數打印字符串會出現不同的效果? 在 Go 語言中,為什麼使用 Println 和 string() 函數打印字符串會出現不同的效果? Apr 02, 2025 pm 02:03 PM

Go語言中字符串打印的區別:使用Println與string()函數的效果差異在Go...

Go語言中用於浮點數運算的庫有哪些? Go語言中用於浮點數運算的庫有哪些? Apr 02, 2025 pm 02:06 PM

Go語言中用於浮點數運算的庫介紹在Go語言(也稱為Golang)中,進行浮點數的加減乘除運算時,如何確保精度是�...

Go語言中`var`和`type`關鍵字定義結構體的區別是什麼? Go語言中`var`和`type`關鍵字定義結構體的區別是什麼? Apr 02, 2025 pm 12:57 PM

Go語言中結構體定義的兩種方式:var與type關鍵字的差異Go語言在定義結構體時,經常會看到兩種不同的寫法:一�...

使用 sql.Open 時,DSN 傳空為什麼不報錯? 使用 sql.Open 時,DSN 傳空為什麼不報錯? Apr 02, 2025 pm 12:54 PM

使用sql.Open時,DSN傳空為什麼不報錯?在Go語言中,sql.Open...

Go語言中哪些庫是由大公司開發或知名的開源項目提供的? Go語言中哪些庫是由大公司開發或知名的開源項目提供的? Apr 02, 2025 pm 04:12 PM

Go語言中哪些庫是大公司開發或知名開源項目?在使用Go語言進行編程時,開發者常常會遇到一些常見的需求,�...

See all articles