概述
new()
函数为数据类型 T 调配一块内存,初始化为类型 T 的零值,返回类型为指向数据的指针,能够用于所有数据类型。
make()
函数除了为数据类型 T 分配内存外,还能够指定长度和容量,返回类型为数据的初始化构造,只限于 切片
, Map
, 通道
。
make
什么时候用
申明并初始化 切片, Map, 通道(前面会讲到)。
为什么定义
为什么专门针对切片, Map 和 通道类型定义一个 make
函数呢?
因为这 3 种数据类型要求应用时必须实现初始化,未初始化就应用可能会引发谬误,具体规定如下:
- 未初始化的切片值为
nil
, 如果间接获取或设置元素数据会报错 - 未初始化的
Map
值为nil
, 如果间接设置元素数据会报错 - 未初始化的
通道
值为nil
, 发送数据和接收数据会阻塞 (详情在前面通道章节介绍)
未初始化的切片
package main
func main() {var s []int
// 间接获取值: 报错
_ = s[0]
// 间接设置值: 同样报错
//s[0] = 100
}
// $ go run main.go
// 输入如下
/**
panic: runtime error: index out of range [0] with length 0
...
exit status 2
*/
未初始化的 Map
package main
func main() {var m map[int]string
// 间接设置值: 报错
m[100] = "hello world"
}
// $ go run main.go
// 输入如下
/**
panic: panic: assignment to entry in nil map
...
exit status 2
*/
append()
为什么切片即便是 nil
, 却能够调用 append()
函数呢? 因为 append()
函数外部实现中做了兼容,如果切片为 nil
,
那么会先申请好须要的内存空间,而后在复制给切片,等于 笼罩掉原来的切片
,这样就不会报错了。
应用 new 初始化切片和 Map
如果咱们不应用 make()
函数创立切片和 Map
能够吗?当然是能够的,new()
函数能够创立任何数据类型,当然也包含切片和 Map
,
然而 new()
函数返回的指针指向的是类型的 零值
,对于切片和 Map
来说,零值仍然是 nil
, 这又回到了下面的问题。
new() 创立的切片
package main
import "fmt"
func main() {s := new([]int)
fmt.Printf("s type = %T, val = %#v\n", *s, *s)
// 间接获取值: 报错
_ = (*s)[0]
// 间接设置值: 同样报错
//s[0] = 100
}
// $ go run main.go
// 输入如下
/**
s type = []int, val = []int(nil)
panic: runtime error: index out of range [0] with length 0
...
exit status 2
*/
new() 创立的 Map
package main
import "fmt"
func main() {m := new(map[int]string)
fmt.Printf("s type = %T, val = %#v\n", *m, *m)
// 间接设置值: 报错
(*m)[100] = "hello world"
}
// $ go run main.go
// 输入如下
/**
m type = map[int]string, val = map[int]string(nil)
panic: assignment to entry in nil map
...
exit status 2
*/
new
什么时候用
除了 切片, Map, 通道(前面会讲到) 以外的其余数据类型。
小结
初始化 切片
, Map
, 通道
三种数据类型时,应用 make()
函数,初始化其余数据类型时,应用 new()
函数。