• Golang make 与 new 函数的区别


    这两个函数都用于分配内存,但两者之间仍然有一些差异。本文介绍它们之间的差异,以及各自的应用场景。简言之,new分配内存但不初始化内存;make分配内容并初始化内存,所谓初始化即给变量赋初始值。举例,字符串为空,整型为0,布尔变量为false。

    new

    首先看下new函数定义:

    // The new built-in function allocates memory. The first argument is a type,
    // not a value, and the value returned is a pointer to a newly
    // allocated zero value of that type.
    func new(Type) *Type
    
    • 1
    • 2
    • 3
    • 4

    new函数参数是类型,返回值是指针,指向该类型的内存地址,分配的内存被设为零值,即该类型的零值,就是说字符串为空,整型为0,布尔变量为false等。

    下面请看示例:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	type P struct {
    		Name string
    		Age  int
    	}
    
    	var a *[2]int
    	var s *string
    	var b *bool
    	var i *int
    	var ps *P
    
    	a = new([2]int)
    	s = new(string)
    	b = new(bool)
    	i = new(int)
    	ps = new(P) //structure
    
    	fmt.Println(a, " ", *a)
    	fmt.Println(s, " ", *s)
    	fmt.Println(b, " ", *b)
    	fmt.Println(i, " ", *i)
    	fmt.Println(ps, " ", *ps)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    输出结果:

    &[0 0]   [0 0]
    0xc00004c250        
    0xc00001a098   false
    0xc00001a0c0   0    
    &{ 0}   { 0}        
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面是基本类型,下面看slice、map、Chan,new操作的结果进行对比:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	//map operation
    	var mp *map[string]string
    	mp = new(map[string]string)
    	//*mp = make(map[string]string)
    	// if previous line is omitted, it will pan "Pan: assignment to entry in nil map"
    	(*mp)["name"] = "lc"
    	fmt.Println((*mp)["name"])
    
    	//slice operation
    	var ms *[]string
    	ms = new([]string)
    	//*ms = make([]string, 5)
    	// if previous line is deleted, it will "panic: runtime error: index out of range"
    	(*ms)[0] = "lc"
    	fmt.Println((*ms)[0])
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    我们看到slice,map,channel以及其他的引用类型初始化时为nil,nil不能被直接赋值。new也不能分配内存,还需要make分配内存。

    make

    首先查看make函数的定义:

    // The make built-in function allocates and initializes an object of type
    // slice, map, or chan (only). Like new, the first argument is a type, not a
    // value. Unlike new, make's return type is the same as the type of its
    // argument, not a pointer to it. The specification of the result depends on
    // the type:
    //  Slice: The size specifies the length. The capacity of the slice is
    //  equal to its length. A second integer argument may be provided to
    //  specify a different capacity; it must be no smaller than the
    //  length. For example, make([]int, 0, 10) allocates an underlying array
    //  of size 10 and returns a slice of length 0 and capacity 10 that is
    //  backed by this underlying array.
    //  Map: An empty map is allocated with enough space to hold the
    //  specified number of elements. The size may be omitted, in which case
    //  a small starting size is allocated.
    //  Channel: The channel's buffer is initialized with the specified
    //  buffer capacity. If zero, or the size is omitted, the channel is
    //  unbuffered.
    func make(t Type, size ...IntegerType) Type
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    make函数返回值与参数类型一致,而不是指针,因为make仅初始化slice,map,channel等的内存,而这些类型是引用类型,不需要返回指针。请看示例:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	mm := make(map[string]string)
    	mm["name"] = "lc"
    	fmt.Println(mm["name"])
    
    	mss := make([]int, 2)
    	mss[0] = 100
    	fmt.Println(mss[0])
    
    	ch := make(chan int, 1)
    	ch <- 100
    
    	fmt.Println(<-ch)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    总结

    make仅用于分配并初始化slice,map,channel类型,而new能分配任何数据类型。new返回指针(Type, *Type),make返回引用(Type).另外new仅分配空间,make分配的空间之后被清空并初始化。

    这里顺便说下指针与引用的区别:

    • 指针
      指针是保存另一个变量的内存地址的变量。指针需要用*操作符解引用,以访问它所指向的内存位置。

    • 引用
      引用变量是别名,即已经存在的变量的另一个名称。引用和指针一样,也是通过存储对象的地址来实现的。引用可以被认为是一个具有自动间接功能的常量指针(不要与指向常量值的指针混淆!),也就是说,编译器会为你应用*操作符。

  • 相关阅读:
    CCPC Finals 2021 (A F G J L)
    用HTML+CSS做一个简单好看的校园社团网页
    【iOS-UIImagePickerController访问相机和相册】
    基于javaweb的学生管理系统
    声纹技术(二):音频信号处理基础
    “蔚来杯“2022牛客暑期多校训练营9 I题: The Great Wall II
    WPF 截图控件之文字(七)「仿微信」
    开发 integration 云云对接
    scala
    yolov5和yolov7之实例分割训练
  • 原文地址:https://blog.csdn.net/neweastsun/article/details/127656142