Preface
This article mainly introduces the use and difference between new and make in Go language. Regarding the two built-in functions in Go language, new and make are mainly used to create allocated type memory. When we define the generation variables, we may feel a little confused and don’t know when to use make and when to use new. In fact, their rules are very simple. Let’s use some examples to illustrate their differences and use.
Variable declaration
var i int var s string
We can use the var keyword and then use it 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 type int is 0, the zero value of type string is "", and the zero value of reference type is nil.
For the two types of declarations in the example, we can use them directly and assign them to output them. But what if we change to pointer type?
package main import ( "fmt" ) func main() { var i *int *i=10 (*i) }
$ go run panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4849df] goroutine 1 [running]: () /home/onenewcode/go/src/golang_deeper/make_new/t
From this prompt, we can see that for variables of reference type, we not only need to declare them, but also allocate content space for them, otherwise where will our values be placed? This is the reason for the above error message.
The declaration of value type is not needed because it has been allocated for us by default.
Because I want to allocate memory, today's memory allocation functions new and make are derived.
new
How do we solve the above problem? Since we know that there is no memory allocated for it, then we can allocate one using new.
func main() { var i *int i=new(int) *i=10 (*i) }
Now run the program again, perfect PASS, print 10. Now let's take a 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
Translate the above English to obtain the following information:
It only accepts one parameter, which is a type. After allocating memory, it returns a pointer to the memory address of that type. At the same time, please note that it also places the allocated memory to zero, that is, the zero value of the type.
In our example, if *i=10 is not printed, then 0 is printed. The benefits of setting the new function to zero are not reflected here. Let's take another example.
package main import ( "fmt" "sync" ) type user struct { lock name string age int } func main() { u := new(user) //The default memory allocated to u is 0 () //It can be used directly, because lock is 0, it is unlocked. = "Zhang San" () (u) }
run
$ go run
&{{0 0} Zhang San 0}
I don't need to initialize the lock field in the user type in the example, it can be used directly, and there will be no invalid memory reference exception because it has already been valued zero.
This is new, which always returns a pointer of type, pointing to the memory address of the allocated type.
make
make is also used for memory allocation, but it is different from new.
It is only used for,chan,map,slicememory creation, and the type it returns is these three types themselves, not their pointer type, because these three types are reference types, so there is no need to return their pointer.
Note that because these three types are reference types, they must be initialized, but not set to zero value, this is different from new.
func make(t Type, size ...IntegerType) Type
As you can see from the function declaration, the type returned is still the same.
The similarities and similarities between make and new
Similarities:
- All are built-in functions for memory management.
- All involves the allocation of dynamic memory.
Differences:
-
Purpose and applicable types:
- new(T): Applicable to any type of memory allocation, including but not limited to structures, arrays, pointers, etc. It allocates memory for the specified type T, initializes the memory to its zero value, and returns a pointer to that memory area (type *T).
- make(T, args…): only applies to three built-in reference types, namely slices, maps, and channels. For these three types, make not only allocates memory, but also performs additional initialization operations, such as setting internal data structures, hash table sizes, and channel buffers. The return value of the make function is directly the initialized slice/map/channel type, not a pointer.
-
How to use and return values:
- The call form of new() is relatively simple: p := new(Type), which returns a pointer to the newly allocated memory.
- The call to make() needs to provide additional parameters to initialize the corresponding type, such as length and optional capacity when creating slices: s := make([]int, length, capacity); no size is required when creating map or channel, but the buffer size can be specified for the channel.
Initialization content:
new() only does the most basic memory allocation and fills with zero values.
-
The content of the make() initialization is more complicated, for example:
- For slices, the underlying array is created and the length and capacity are set;
- For maps, an empty hash table is initialized;
- For channels, a communication data structure is created and buffers can be optionally allocated.
In short, in Go, you use new() when you need to allocate memory for custom types or primitive types without specific initialization logic involved; and when you need to initialize built-in reference types such as slice, map, or channel, you must use make().
This is the article about the difference between make and new use in Golang. For more related content on Golang, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!