Skip to main content

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 {
//省略无关代码
}

总结