FeelingLife FeelingLife
首页
  • Go

    • Go基础知识
  • Python

    • Python进阶
  • 操作系统
  • 计算机网络
  • MySQL
  • 学习笔记
  • 常用到的算法
  • Docker
  • Kubernetes
  • Observability
  • 容器底层
其他技术
  • 友情链接
  • 收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

xuqil

一介帆夫
首页
  • Go

    • Go基础知识
  • Python

    • Python进阶
  • 操作系统
  • 计算机网络
  • MySQL
  • 学习笔记
  • 常用到的算法
  • Docker
  • Kubernetes
  • Observability
  • 容器底层
其他技术
  • 友情链接
  • 收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 环境部署

  • 测试

  • 反射

  • 数据库操作

  • 并发编程

  • 内存管理

    • Golang 逃逸分析
    • new 和 make 的区别
      • new
        • 函数签名
        • 作用
      • make
        • 函数签名
        • 作用
      • new与make的异同
        • 相同点
        • 不同点
  • 线程安全

  • Go 技巧

  • middleware

  • 第三方库

  • Go各版本特性

  • 《go基础知识》
  • 内存管理
xuqil
2023-04-22
目录

new 和 make 的区别

# make 和 new 的区别

# new

# 函数签名

new的函数签名:

func new(Type) *Type
1

参数说明:

  • Type:需要new的类型。
  • 返回值是指向Type的指针,新分配的值为Type的零值。

# 作用

new主要用于分配内存, 但与其它语言中的同名函数不同,它不会初始化内存,只会将内存置零。 也就是说,new(T) 会为类型为T的新项分配已置零的内存空间, 并返回它的地址(即*T)。用 Go 的术语来说,它返回一个指针, 该指针指向新分配的,类型为T的零值。

例如下面这个例子,i是一个int类型的指针,但是没有分配内存空间,因此是不能赋值的。执行这个测试会报错:invalid memory address or nil pointer dereference。

/*
TestVariable 会报错

panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4f503b]
*/

func TestVariable(t *testing.T) {
	var i *int
	*i = 10
	t.Log(*i)
}
1
2
3
4
5
6
7
8
9
10
11
12
13

现在使用new来分配内存:

func TestNew_int(t *testing.T) {
	var i *int
	i = new(int)
	fmt.Println(*i) // 0 提示:int 的零值为 0
	*i = 1
	fmt.Println(*i) // 1
}
1
2
3
4
5
6
7

现在重新执行这个测试,可以通过了。

# make

# 函数签名

make的函数签名:

func make(t Type, size ...IntegerType) Type
1

make和new一样,第一个参数是一个类型,而不是一个值。与new不同的是,make的返回类型与其参数的类型相同,而不是指向它的指针。

# 作用

make不同于new,它仅限于slice、map和chan的初始化(分配内存空间,而非置零),同时它接收三个参数。第一个参数是类型,第二个是该类型的长度,第三个是该类型的容量。出现这种用差异的原因在于,这三种类型本质上为引用数据类型,它们在使用前必须初始化。

注意:如果第一个参数是map类型,那么make只接收两个参数,第二个是容量。

下面这个例子是创建一个长度为0,容量为10的int类型的切片(slice):

func TestMake_slice(t *testing.T) {
	l := make([]int, 0, 10)
	fmt.Println(l == nil)                           // false
	fmt.Printf("len: %d cap: %d\n", len(l), cap(l)) // len: 0 cap: 10
	l = append(l, 1)
	fmt.Println(l) // [1]
}
1
2
3
4
5
6
7

使用new来创建的切片并不能指定长度和容量,返回的是指向切片的指针:

func TestNew_slice(t *testing.T) {
	l := new([]int)
	fmt.Println(*l == nil)                            // true
	fmt.Printf("len: %d cap: %d\n", len(*l), cap(*l)) // len: 0 cap: 0
	*l = append(*l, 1)
	fmt.Println(*l) // [1]
}
1
2
3
4
5
6
7

# new与make的异同

# 相同点

  • new和make都是用于给指定的类型分配内存空间。

# 不同点

  • make仅限于slice、map和chan的初始化。
  • make接收的参数比new多,它的返回值是slice、map或chan这个三个类型本身,而不是它们的指针类型,因为这三种就是引用类型。
  • new用于类型内存分配(初始化值为类型的零值),返回值是指向Type的指针。

提示:不要使用new,永远用 make 来构造 map。如果你错误的使用new分配了一个引用对象,你会获得一个空引用的指针,相当于声明了一个未初始化的变量并且取了它的地址:

func TestNew_map(t *testing.T) {
	m := new(map[string]int)
	fmt.Println(*m == nil) // true
	(*m)["key"] = 1        // panic: assignment to entry in nil map
}
1
2
3
4
5
上次更新: 2024/05/29, 06:25:22
Golang 逃逸分析
Go 的 string 是否线程安全

← Golang 逃逸分析 Go 的 string 是否线程安全→

最近更新
01
VXLAN互通实验
05-13
02
VXLAN
05-13
03
VLAN
05-13
更多文章>
Theme by Vdoing | Copyright © 2018-2025 FeelingLife | 粤ICP备2022093535号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式