What is the difference between make and new in Go

Posted by DaveM on Sun, 20 Feb 2022 12:31:10 +0100

This paper mainly introduces the use and difference between new and make in Go language. New and make are two built-in functions in Go language, which are mainly used to create allocated type memory. When we define the generated variables, we may feel a little confused. In fact, their rules are very simple. Let's illustrate their differences and uses through some examples.

1. Declaration of variables

var i int
var s string

The declaration of variables can be through the var keyword, and then can be used in the program. When we do not specify the default value of variables, the default value of these variables is their zero value. For example, the zero value of int type is 0, the zero value of string type is "", and the zero value of reference type is nil.

For the two types of declarations in the example, we can directly use them to assign and output them. But what if we change to pointer type?

package main

import (
 "fmt"
)

func main() {
   var i *int
   *i=10
   fmt.Println(*i)
}

Print results

$ go run test1.go 
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4849df]

goroutine 1 [running]:
main.main()
	/home/itheima/go/src/golang_deeper/make_new/t

From this prompt, we can see that for variables of reference type, we should not only declare it, but also allocate content space for it. Otherwise, where do we put our values? This is the reason for the error prompt above.

The declaration of value type is unnecessary because it has been allocated for us by default.

To allocate memory, introduce today's new and make.

2. new

How can we solve the above problems? Now that we know there is no memory allocated for it, let's use new to allocate one.

func main() {
  
   var i *int
   i=new(int)
   *i=10
   fmt.Println(*i)
  
}

Now run the program, perfect PASS, print 10. Now let's look at the built-in function 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

It only accepts one parameter, which is a type. After allocating memory, it returns a pointer to the memory address of this type. Also note that it also sets the allocated memory to zero, which is the zero value of the type.

In our example, if there is no * i=10, then 0 is printed. The advantage of setting the memory of the new function to zero is not reflected here. Let's take another example.

package main

import (
    "fmt"
    "sync"
)

type user struct {
    lock sync.Mutex
    name string
    age int
}

func main() {

    u := new(user) //By default, all memory allocated to u is 0

    u.lock.Lock()  //It can be used directly because lock is 0, which is the unlocked state
    u.name = "Zhang San"
    u.lock.Unlock()

    fmt.Println(u)
}

Operation results

$ go run test2.go 
&{{0 0} Zhang San 0}

The lock field in the user type in the example can be used directly without initialization. There will be no invalid memory reference exception because it has been zero.

This is new. It always returns a pointer to the type, pointing to the memory address of the allocated type.

3. make

make is also used for memory allocation, but it is different from new.

It is only used for memory creation of chan, map and slice, and the type it returns is the three types themselves, not their pointer types. Because these three types are reference types, it is not necessary to return their pointers.

Note that because these three types are reference types, they must be initialized, but not set to zero. This is different from new.

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

As you can see from the function declaration, this type is still returned.

4. The difference between make and new

identical

  • Heap memory space allocation

Different

  • make: it is only used for slice, map and channel initialization. It is irreplaceable
  • new: used for type memory allocation (initialization value is 0), not commonly used

New is not commonly used, so there is a built-in function of new, which can allocate a piece of memory for us to use, but it is not commonly used in real coding. We usually use phrase statement and literal quantity of structure to achieve our purpose, such as:

i : =0
u := user{}

Make is irreplaceable. When using slice, map and channel, we still need to use make for initialization before we can operate them.

Topics: Go Back-end