The use and differences between new and make in Go language are discussed in detail

  • 2020-06-07 04:38:40
  • OfStack

preface

This article introduces the use and differences between the new and make functions in Go. In Go, new and make are two built-in functions that are used to create allocation-type memory. When we define the generated variables, we may feel a little confused. In fact, their rules are very simple. Below, we will illustrate their differences and use through 1 examples.

Declaration of variables


var i int
var s string

Variable declarations can be made using the var keyword, which can then 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 is 0, the zero value of string is "", and the zero value of reference type is nil.

For the two types of declarations in the example, we can simply use them to assign output. But what if we switch to a reference type?


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

What does this example print out? 0 or 10 & # 63; . All of the above is wrong. painc will be run for the following reasons:


panic: runtime error: invalid memory address or nil pointer dereference

As you can see from this tip, for a variable of reference type, not only do we need to declare it, we also need to allocate content space for it, otherwise where do we put our values? This is the reason for the error above.

The declaration of the value type is not required because it is already assigned by default.

To allocate memory, we derive today's new and make.

new

How can we solve the above problems? Now that we know we're not allocating memory, let's use new to allocate one.


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

Now run the program again, 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 takes only one argument, which is a type, and when allocated, returns a pointer to the memory address of that type. Notice that it also sets the allocated memory to zero, which is the zero value of the type.

In our example, if *i=10 is not present, then 0 is printed. This doesn't capture the benefit of the new function of zero memory, so let's look at another example.


func main() {
 u:=new(user)
 u.lock.Lock()
 u.name = " zhang 3"
 u.lock.Unlock()
 fmt.Println(u)
}
type user struct {
 lock sync.Mutex
 name string
 age int
}

The lock field of the user type in the example, which I did not initialize, can be used directly without invalid memory reference exceptions because it is already null.

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

make

make is also used for memory allocation, but unlike new, it is only used for memory creation for chan, map, and slices, and it returns the types of the three types themselves, not their pointer types, because the three types are reference types, so there is no need to return their Pointers.

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


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

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

Similarities and differences between the two

So it's clear from here that both are memory allocations (on the heap), but make is only used for the initialization of slice, map, and channel (non-zero); new is used for type memory allocation and memory is set to zero. So when we write a program, we can make a good choice according to our needs.

make returns the three reference types themselves; new returns a pointer to the type.

Actually new is not used very often

So there's a built-in function called new that gives us a block of memory to use, but it's not used very often in real coding. We usually use the phrasal declaration and literal structure to achieve our purpose, such as:


i:=0
u:=user{}

This is simpler and more convenient, and does not involve more troublesome operations like Pointers.

There is no substitute for the make function. When we use slice, map, and channel, we still have to use make to initialize before we can manipulate them.

conclusion


Related articles: