Golang数据初始化,零值以及一些陷阱
基础不牢,地动山摇
不像Python这种动态语言,遇见对象就是一言不合的赋给变一个变量,然后查看;而Go语言是静态类型语言,因此变量是有明确类型的,编译器也会检查变量类型的正确性。
1. 变量的初始化
1.1 声明
声明变量的一般形式是使用 var 关键字:var name type
,其中,var 是声明变量的关键字,name 是变量名,type 是变量的类型。
也可以进行批量声明:
1 |
|
1.2 初始化
变量初始化的标准格式var 变量名 类型 = 表达式
,例如var age int = 25
;在标准格式的基础上,将 int 省略后,编译器会尝试根据等号右边的表达式推导 age 变量的类型:var age = 25
,这个很容易理解。
1.3 短变量声明并初始化
var 的变量声明还有一种更为精简的写法,例如:age := 100
,这是Go语言的推导声明写法,编译器会自动根据右值类型推断出左值的对应类型,但只能在函数中使用。
2. Go类型默认的零值
不带初始值的变量声明会被设置为它们的零值:
- 0 for all integer types
- 0.0 for floating point numbers
- false for booleans
- “” for strings
- nil for interfaces, slices, channels, maps, pointers and functions
如果array或struct声明后未指定值,则其中的元素的字段将为零值。该初始化以递归方式完成:
1 |
|
3. make和new的区别
Go语言中new和make是内建的两个函数,主要用来创建分配类型内存。 在我们定义生成变量的时候,可能会觉得有点迷惑,其实他们的规则很简单。
3.1 new
new(T)
为一个 T 类型新值分配空间并将此空间初始化为 T 的零值,返回的是新值的地址,也就是 T 类型的指针 *T,该指针指向 T 的新分配的零值。new要点:
- 内置函数 new 分配空间
- 传递给new 函数的是一个类型,不是一个值
- 返回值是 指向这个新分配的零值的指针
3.2 make
make(T, args)
返回的是初始化之后的 T 类型的值,这个新值并不是 T 类型的零值,也不是指针 *T,是经过初始化之后的 T 的引用。make 也是内建函数,你可以从官方文档这里看到,它的函数原型 比 new 多了一个(长度)参数,返回值也不同.
make 只能用于 slice,map,channel 三种类型, 并且只能是这三种对象。 和 new 一样,第一个参数是 类型,不是一个值. 但是make 的返回值就是这个类型(即使一个引用类型),而不是指针.具体的返回值,依赖具体传入的类型.
3.3 两者区别
new(T)
返回 T 的指针 *T 并指向 T 的零值。make(T)
返回的初始化的 T,只能用于 slice,map,channel,要获得一个显式的指针,使用new进行分配,或者显式地使用一个变量的地址。
new 函数分配内存,make函数初始化。
具体可以看mojoyv的文章 以及三月沙的理解 Go make 和 new 的区别,包含很多代码例子
4. 一些初始化相关的陷阱
4.1 在nil map中赋值
1 |
|
4.2 无效的内存地址或nil指针取消引用
1 |
|
上面代码会报错:
1 |
|
未初始化的指针是nil,我们没法使用它,有两种解决方案:
创建一个指针
1 |
|
或者直接跳过指针,用值接收者调用指针方法
1 |
|
4.3 一个copy错误
1 |
|
很明显这里的src是一个slice的零值nil,要完整副本的COPY,必须分配容量足够大的目标切片:
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!