在Golang中声明变量会用到make和new两个重要函数
- make内置函数分配并初始化类型(slice, map, 以及 chan)为的对象。与new一样,第一个参数是类型,而不是值. 和new相比不同的是,make函数返回的是与参数相同的返回值,不是指针。这三种类型就是引用类型,所以就没有必要返回他们的指针了。
func make(t Type, size ...IntegerType) Type
- new函数用于分配内存,第一个参数为类型(不是值),返回的结果是一个指针(分配对应类型的0值)
func new(Type) *Type
总结:
1. 二者都是用来做内存分配的。
2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
3. 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。
值类型与引用类型
- 值类型:变量直接存储值,内存通常在栈中分配
- 引用类型:变量存储的是一个地址,这个地址对于的空间才是真正的存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,改地址对应的数据空间就成为了一个垃圾,由GC来回收
代码示例
- new函数
package main
import "fmt"
func main() {
var a = new(int)
fmt.Println(a)
}
// 输出地址:0xc000014088
- make函数
package main
import "fmt"
func main() {
var a = make(map[string]string, 1)
a["name"] = "小a"
fmt.Println(a)
}
// 输出:map[name:小a]
- 不使用new与make时
说明:Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串。 布尔型变量默认为false。 切片、函数、指针变量的默认为nil。
package main
import "fmt"
func main() {
// a 引用类型
var a = make(map[string]int)
// b 引用类型
var b map[string]int
// 值类型
var c [5]int
var d *int
// 对a赋值不报错(因为已分配地址)
a["name"] = 1
// 对b赋值报错
// b["name"] = 1
// 对c赋值
c[0] = 1
// 引用类型
// 不初始化报错
d = new(int)
*d = 1
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(*d)
}
结论:虽然声明变量的时候,会自动对变量对应的内存区域进行初始化成其类型的默认值,但是引用类型的变量必须使用new或者make函数分配内存才可以进行变量的赋值操作。而值类型不需改改操作。
就是说,变量声明虽然会初始化,但是引用类型必须要使用new或者make对值进行初始化,如果引用类型的值没有初始化那么是无法直接使用的