allocation
内存分配
程序的运行都需要内存
使用内存时需要内存申请,进行内存分配
在go语言中:内存分配是由go语言自己管理,开发者只需申请变量,它就会根据变量类型自动分配相应的内存
只要涉及到变量的声明、初始化就会涉及到内存的分配
变量的声明
一个数据类型,在声明初始化后都会赋值给一个变量
变量存储了程序运行时所需要的数据
//下面的代码只是声明了变量并未初始化,所以会被赋予该变量类型的零值也就是空字符串
var s string
//下面的代码只是声明了变量并未初始化,所以会被赋予该变量类型的零值也就是nil
var s1 *string
变量的赋值
变量可通过=
运算符赋值,也就是修改变量的值
如在声明一个变量时给这个变量赋值
这种操作称为变量的初始化
对于值类型,变量声明的时候即使没有初始化,该变量也会有分配好的内存(eg: var wg sync.WaitGroup
),但是指针却不是
来看下面的例子:
值类型的变量可以直接赋值
package main
import "fmt"
func main() {
var s string
s = "scott"
fmt.Println(s) //scott
}
指针类型的变量赋值前必须先分配内存
虽然IDE没报错,但是运行时出错了
原因是空指针nil没有内存地址,你无法使用它
如要对一个变量赋值,这个变量必须有对应分配好的内存
这样才可以对这块内存操作,完成赋值的目的
小提示:不止赋值操作,对于指针变量,如果没有分配内存取值操作一样会报nil异常,因为没有可以操作的内存
new or make
基于内存分配我们引出内置函数new和make,他们的返回值都是指针
现在来讲一下它们的不同及使用场景
new
以上示例报错因为没有分配内存,那我们给它分配内存不就好了
我们用new来改造一下代码:
发现是ok的
我们来看看new的源代码:
new的作用:根据传入的类型,申请一块内存,然后返回指向这块内存的指针,指针指向的数据就是该类型的零值
比如我传入一个string,那么就得到一个string类型的指针,这个指针指向的是空字符串
不同于java,可以看到s1,s2内存地址是不一样的
eg:
var s string = "scott"
s1:="scott"
我们可以用工厂函数
但是这个函数又不太通用,我们来改造一下
由此我们可以生产出各种不同的person指针变量
make
我们调用make的时候其实调用的是下面这个函数
src/runtime/map.go
// makemap implements Go map creation for make(map[k]v, hint).
func makemap(t *maptype, hint int, h *hmap) *hmap {
//省略无关代码
}