Go语言make函数详解:初始化切片、映射和通道

文章目录

在 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 创建不同类型的通道:

  1. 无缓冲通道,不能存储任何数据,只能充当数据管道:
    // 创建一个无缓冲的整数通道
    out := make(chan int)
    
  2. 可以存储一定数量数据的缓冲通道
    // 创建一个缓冲通道,最多可以容纳 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 语言规范


也可以看看