在go语言中, 通过var声明变量时, 不指定默认值时, 就是使用他们的零值。 例如int类型的零值是0,string类型的零值是"",引用类型的零值是nil。
如果是引用类型, 那么直接通过var声明是不够的,还需用new或make来分配内存。
var b *int
//b := new(int)
fmt.Println(*b)
// 会报错
//panic: runtime error: invalid memory address or nil pointer dereference
golang的new和make主要区别如下:
1、make只能用来分配及初始化类型为slice,map,chan的数据;new可以分配任意类型的数据
2、new分配返回的是指针,即类型*T;make返回引用,即T;
3、new分配的空间被清零,make分配后,会进行初始化。(怎么理解)
4、对于struct的分配和初始化,除了可以使用new外,还可以这样做: T {},例如
package main
import (
"fmt"
"os"
)
func TestAlloc() {
type T struct {
n string
i int
f float64
fd *os.File
b []byte
s bool
}
var t1 *T
t1 = new(T)
fmt.Println(t1)
t2 := T{}
fmt.Println(t2)
t3 := T{"hello", 1, 3.1415926, nil, make([]byte, 2), true}
fmt.Println(t3)
}
func main() {
TestAlloc()
}
&{ 0 0 <nil> [] false}
{ 0 0 <nil> [] false}
{hello 1 3.1415926 <nil> [0 0] true}
值得注意的是,如果使用T{}的方式初始化变量的话:
1、与C语言不同,T{}分配的局部变量是可以返回的,且返回后该空间不会释放,例如
import "fmt"
type T struct {
i, j int
}
func a(i, j int) T {
i := T { i, j}
return i
}
func b() {
t = a(1, 2)
fmt.Println(t)
}
2、一个语法问题
使用T{}来初始化时,符号}不能单独占一行,否则会报错。
其他思考:
(a) 怎么理解 new分配的空间被清零,make分配后,会进行初始化?
答: make只用于slice, map, channel。 以slice为例。slice的零值是nil, 但是用make初始化后slice 是一个初始化的slice,即slice的长度、容量、底层指向的array都被make完成初始化。
例如make([]int,3)此时slice内容被类型int的零值填充,形式是[0 0 0],长度为3,容量不填默认等于长度这个参数。
(b) 怎么理解 make返回引用
答: 如果不特殊声明,go的函数默认都是按值穿参,即通过函数传递的参数是值的副本,在函数内部对值修改不影响值的本身,但是make(T,args)返回的值通过函数传递参数之后可以直接修改,即 map,slice,channel 通过函数穿参之后在函数内部修改将影响函数外部的值。
网友评论