揭秘 Go 中的 new() 和 make() 函數(shù)
Go(或 Golang)是一種現(xiàn)代、靜態(tài)類型、編譯型的編程語言,專為構建可擴展、并發(fā)和高效的軟件而設計。它提供了各種內置的函數(shù)和特性,幫助開發(fā)人員編寫簡潔高效的代碼。其中包括 new() 和 make() 函數(shù),這兩個函數(shù)乍看起來可能相似,但在 Go 中用于不同的目的,對于內存分配和數(shù)據(jù)初始化至關重要。
在本博客文章中,我們將探討 new() 和 make() 函數(shù)之間的區(qū)別,了解何時以及如何有效地使用它們。
new() 和 make() 函數(shù)
new() 和 make() 都是 Go 中的內置函數(shù),用于分配內存。然而,它們用于不同的數(shù)據(jù)類型和場景:
new() 函數(shù):
- new() 用于為值類型(例如整數(shù)、浮點數(shù)、結構體)分配內存,并返回指向新分配的零值的指針。
- 它接受一個參數(shù),即類型,并返回該類型的指針。
make() 函數(shù):
- make() 用于創(chuàng)建和初始化切片、映射和通道,這些都是 Go 中的引用類型。
- 它根據(jù)類型的不同接受兩個或三個參數(shù),并返回一個已初始化(非零值)的值,可以立即使用。
理解 new() 函數(shù)
new() 函數(shù)的語法非常簡單,如下所示:
func new(Type) *Type
這里的 Type 表示我們想要為其分配內存的值的類型。讓我們看一個如何使用 new() 的示例。
在這個示例中,我們使用 new() 創(chuàng)建了 Person 結構體的一個新實例,然后使用指針分配值給其字段。
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
// Using new() to allocate memory for a Person struct
p := new(Person)
fmt.Printf("%T\n", p)
// Accessing struct fields using the pointer
p.Name = "Alice"
p.Age = 30
// Displaying the values
fmt.Println("Name:", p.Name)
fmt.Println("Age:", p.Age)
}
這個程序將產生如下所示的輸出。
> go run main.go
*main.Person
Name: Alice
Age: 30
理解 make() 函數(shù)
make() 函數(shù)的語法取決于它所用于的類型。
(1) 對于切片(Slices)
func make([]Type, len, cap) []Type
- Type:切片將保存的元素類型。
- len:切片的初始長度。
- cap:切片的容量,這是可選的,并用于指定底層數(shù)組的容量。如果未提供,它默認與長度相同。
使用 make() 創(chuàng)建切片的示例:
package main
import "fmt"
func main() {
// Using make() to create a slice of integers
numbers := make([]int, 5, 10)
// Displaying the slice's length, capacity, and values
fmt.Println("Length:", len(numbers))
fmt.Println("Capacity:", cap(numbers))
fmt.Println("Values:", numbers)
// Using make() to create a slice of integers
numbersWithoutOptional := make([]int, 5)
// Displaying the slice's length, capacity, and values
fmt.Println("Length:", len(numbersWithoutOptional))
fmt.Println("Capacity:", cap(numbersWithoutOptional))
fmt.Println("Values:", numbersWithoutOptional)
}
此程序將產生如下輸出:
> go run main.go
Length: 5
Capacity: 10
Values: [0 0 0 0 0]
Length: 5
Capacity: 5
Values: [0 0 0 0 0]
(2) 對于映射(Maps)
func make(map[KeyType]ValueType, initialCapacity int) map[KeyType]ValueType
- KeyType:映射中鍵的類型。
- ValueType:與鍵關聯(lián)的值的類型。
- initialCapacity:映射的初始容量。這是可選的,但當預先知道元素數(shù)量時,可以用于優(yōu)化性能。
使用 make() 創(chuàng)建映射的示例:
package main
import "fmt"
func main() {
// Using make() to create a map of string keys and int values
scores := make(map[string]int)
// Adding values to the map
scores["Alice"] = 95
scores["Bob"] = 87
// Displaying the map
fmt.Println("Scores:", scores)
}
> go run main.go
Scores: map[Alice:95 Bob:87]
(3) 對于通道(Channels)
func make(chan Type, capacity int) chan Type
- Type:可以通過通道發(fā)送和接收的值的類型。
- capacity:通道的緩沖區(qū)大小。如果設置為0,通道是無緩沖的。
使用 make() 創(chuàng)建通道的示例:
package main
import (
"fmt"
"time"
)
func main() {
// Using make() to create an unbuffered channel of integers
ch := make(chan int)
// Sending data into the channel using a goroutine
go func() {
for i := 1; i <= 5; i++ {
ch <- i
time.Sleep(time.Second) // Simulating some work before sending the next value
}
close(ch)
}()
// Receiving data from the channel
for num := range ch {
fmt.Println("Received:", num)
}
}
> go run main.go
Received: 1
Received: 2
Received: 3
Received: 4
Received: 5
結論
在本博客文章中,我們解開了 Go 中的 new() 和 make() 函數(shù)的謎團,并解釋了它們的區(qū)別和用途。總結一下:
- 使用 new() 為值類型分配內存,并獲取指向零值的指針。
- 使用 make() 創(chuàng)建和初始化切片、映射和通道(引用類型),并指定它們的類型和初始容量。
理解 new() 和 make() 之間的區(qū)別對于在 Go 中進行高效的內存分配和數(shù)據(jù)初始化至關重要。正確使用這些函數(shù)將在您的 Golang 項目中產生更干凈和更優(yōu)化的代碼。愿您編程愉快!