new vs. make: Understanding the Differences and When to Use Each

In Go, both new and make are used for memory allocation, but they serve different purposes and are used in different contexts. Here's a detailed look at the differences between new and make, and guidelines on when to use each.

new

Syntax:

go
ptr := new(Type)

Example:

go
package main import "fmt" func main() { p := new(int) // Allocates memory for an int and returns a pointer to it fmt.Println(*p) // Output: 0 (zero value of int) *p = 42 fmt.Println(*p) // Output: 42 }

In this example, new(int) allocates memory for an integer, initializes it to 0, and returns a pointer to that integer.

make

Syntax:

go
slice := make([]Type, length, capacity) mapVar := make(map[KeyType]ValueType, capacity) ch := make(chan Type, bufferSize)

Examples:

go
package main import "fmt" func main() { // Creating a slice with make slice := make([]int, 5) // Allocates and initializes a slice of int with length 5 for i := range slice { slice[i] = i * i } fmt.Println(slice) // Output: [0 1 4 9 16] // Creating a map with make m := make(map[string]int) m["foo"] = 1 m["bar"] = 2 fmt.Println(m) // Output: map[foo:1 bar:2] // Creating a channel with make ch := make(chan int, 2) ch <- 1 ch <- 2 fmt.Println(<-ch) // Output: 1 fmt.Println(<-ch) // Output: 2 }

In these examples, make initializes slices, maps, and channels with their internal data structures, making them ready for use.

Key Differences

  1. Types:

    • new can be used with any type, but it returns a pointer to the allocated memory.
    • make is only used with slices, maps, and channels and returns an initialized (but not necessarily filled) value of the type (not a pointer).
  2. Initialization:

    • new zeroes out the memory but does not initialize complex data structures.
    • make initializes the data structures required for slices, maps, and channels.
  3. Return Value:

    • new(Type) returns *Type (a pointer to the type).
    • make(Type, ...) returns Type (a value of the type).

When to Use new

Example:

go
type Node struct { Value int Next *Node } func createNode(value int) *Node { n := new(Node) n.Value = value return n }

When to Use make

Example:

go
func createSlice() []int { s := make([]int, 10) // Create a slice with length 10 return s } func createMap() map[string]int { m := make(map[string]int) // Create an empty map return m } func createChannel() chan int { ch := make(chan int, 5) // Create a buffered channel with capacity 5 return ch }

By understanding the differences between new and make and when to use each, you can allocate memory in Go efficiently and appropriately for different data types and use cases.

Becoming a Senior Go Developer: Mastering Go and Its Ecosystem