在 Go 语言编程中,make 函数扮演着举足轻重的角色,尤其是在初始化切片、映射和通道时。make 函数允许开发者指定数据类型的内存和容量限制,赋予了超越常规构造函数的底层控制能力。
Golang make 函数的基本用法
make
函数是 Go 语言内置的特殊函数,它可以接受不同数量的参数,并返回第一个参数指定的类型的实例:
obj := make(someType, optionalArgument1, optionalArgument2)
在这里,someType
可以是切片、映射或通道。
使用 make 函数创建切片
我们可以使用 make
初始化任何类型的切片:
words := make([]string, 2)
这里,第一个参数是类型,第二个参数是长度。
默认情况下,一个新切片被初始化并填充与指定长度一样多的空值。
因此,在这种情况下,words
的值将是 []string{"", ""}
我们还可以在创建切片时传递第三个参数,即容量。容量表示分配给一个切片的内存量,即使它的长度可能没有那么多。
例如,如果我们也使用容量来创建 words
:
words := make([]string, 2, 5)
需要注意的是,容量参数必须大于长度参数,否则代码将无法编译。
words
的值现在仍然是 []string{"", ""}
,但是底层内存被分配给 5 个字符串值。
len=2 cap=5
|""|""|X|X|X|
因此,如果我们使用 append
添加另一个元素,Go 不会在后台分配更多内存:
words = append(words, "axiaoxin blog")
如果没有分配容量,Go 会采用默认容量。添加更多元素时,Go 会在需要时提供更多容量。因此,如果事先知道切片的大小,指定容量就非常有用,因为每次超过默认容量时我们都可以跳过额外的分配。
需要注意的是,指定容量并没有限制切片的最大长度,而是规定了在添加更多元素时需要重新分配的初始容量。
使用 make 函数创建 map 映射
将 make
与 maps 一起使用并不像 slice 那样简单。
// make 一个空 map
m := make(map[int]string)
// make 一个 n 个元素的 map
m := make(map[int]string, n)
我们依旧可以 make 空的 map 实例,并指定容量,但是这里的容量是一个语言上的示意,并不对分配的确切容量做出任何保证。
Golang 语言规范提到第二个参数是指“大约 n 个元素的初始空间”
使用 make 函数创建 channel 通道
我们可以使用 make 创建不同类型的通道:
- 无缓冲通道,不能存储任何数据,只能充当数据管道:
// 创建一个无缓冲的整数通道 out := make(chan int)
- 可以存储一定数量数据的缓冲通道
// 创建一个缓冲通道,最多可以容纳 3 个整数值 out := make(chan int, 3)
make 函数与 new 函数的区别
Go 语言还有一个内置函数 new
,它经常出现在与 make
类似的场景中,但具有不同的功能。
make
能够分配变量内存并返回所提供类型的实例,而 new 只能初始化空实例,并返回所提供参数的指针。
让我们看一个例子:
// 返回一个包含 1 个默认 (0) int 元素的切片
s1 := make([]int, 1)
// 返回一个指向空切片的指针
s2 := new([]int)
fmt.Println(s1)
fmt.Println(s2)
如果我们运行这段代码,我们将得到:
[0]
&[]
总结
make 函数是 Go 语言中一个多功能的内置函数,可用于初始化不同的数据类型。参数及其意义取决于被初始化的变量类型。 更多关于 make 和 new 函数的详细信息,请参阅 Golang 语言规范。