Memory Allocation Mechanisms in Go: The Design and Application of new() and make()

Dec 02, 2025 · Programming · 13 views · 7.8

Keywords: Go language | memory allocation | new function | make function | pointers | reference types

Abstract: This article delves into the differences and design principles of the new() and make() memory allocation functions in Go. Through comparative analysis, it explains that new() is used to allocate value types and return pointers, while make() is specifically for initializing reference types such as slices, maps, and channels. With code examples, it details why Go retains these two separate functions instead of merging them, and discusses best practices in real-world programming.

Basic Methods of Memory Allocation

In Go, memory allocation and value initialization can be achieved through various methods, including &T{...}, &someLocalVar, new, and make. Each has its characteristics and is suitable for different scenarios. For instance, when using composite literals for allocation, memory allocation and initialization can be performed simultaneously.

Functionality and Limitations of new()

The new function is primarily used to allocate memory for value types and return pointers. It applies to all types, including basic types and structs. For example, new(Point) allocates memory for a Point struct and returns its pointer. However, for certain types like integers, directly using &int is illegal, and new(int) provides a concise solution. Although similar functionality can be achieved with var i int; &i, new(int) is more convenient.

Specialized Scenarios for make()

Unlike new, the make function is specifically designed to initialize three reference types: slices, maps, and channels. It performs allocation and initialization, returning an initialized value rather than a pointer. For example, make(chan int) creates an integer channel, while new(chan int) returns a pointer to a channel, which is often not the desired behavior.

Design Principles: Why Separate new() and make()

From a design perspective, if Go had only one built-in allocation function (hypothetically NEW), the code could become complex. For instance, new(int) would correspond to NEW(*int), and make([]int, 10) to NEW([]int, 10). This design could lead to confusion in the type system, especially for novice programmers, causing misunderstandings. Therefore, separating new and make helps improve code readability and type safety.

Code Examples in Practice

The following example illustrates the difference between new and make:

p := new(chan int)   // p has type *chan int, a pointer to a channel
c := make(chan int)  // c has type chan int, an initialized channel

Additionally, make supports pre-allocation features, such as creating slices with specified capacity and length:

s := make([]int, 5, 10)  // slice with length 5 and capacity 10

For pointer creation, new offers a concise approach:

func newInt() *int {
    return new(int)  // equivalent to var i int; return &i
}

Summary and Best Practices

In Go programming, the choice of allocation function should be based on the type: use new for allocating value types and obtaining pointers, and use make for initializing slices, maps, and channels. This separation design not only simplifies syntax but also enhances the clarity of the type system. Developers should avoid misusing new for reference types or attempting to use make for value types to ensure code efficiency and maintainability.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.