How to Use the new() Function in Go

The `new()` function in Go allocates zeroed memory for a type and returns a pointer to it, whereas `make()` is used only for slices, maps, and channels to initialize their internal data structures.

The new() function in Go allocates zeroed memory for a type and returns a pointer to it, whereas make() is used only for slices, maps, and channels to initialize their internal data structures. Use new() when you need a pointer to a zero-valued variable of any type, including structs, primitives, or arrays.

Here is a practical example showing how new() initializes a struct with zero values and returns a pointer:

package main

import "fmt"

type User struct {
	Name string
	Age  int
}

func main() {
	// new() allocates memory, sets fields to zero values, and returns *User
	u := new(User)
	fmt.Printf("Type: %T, Value: %+v\n", u, *u) // Output: Type: *User, Value: {Name: Age:0}

	// You can immediately assign values to the pointer's fields
	u.Name = "Alice"
	u.Age = 30
	fmt.Printf("Updated: %+v\n", *u) // Output: Updated: {Name:Alice Age:30}

	// new() works with primitives too
	p := new(int)
	*p = 42
	fmt.Printf("Int pointer value: %d\n", *p) // Output: 42
}

A common point of confusion is choosing between new() and the composite literal syntax. While new(T) returns *T with zero values, &T{} also returns *T but allows you to set initial values immediately. In modern Go, the composite literal is often preferred for structs because it is more readable and flexible:

// Using new() - zero values only
u1 := new(User) 
u1.Name = "Bob"

// Using composite literal - cleaner and allows initialization
u2 := &User{Name: "Bob", Age: 25}

Note that new() is rarely used for slices, maps, or channels. For those types, you must use make() to allocate and initialize the underlying data structure; using new() on these types will give you a pointer to a nil slice/map/channel, which is usually not what you want.

// Incorrect for slices: returns *[]int pointing to a nil slice
s1 := new([]int) 

// Correct for slices: allocates the underlying array
s2 := make([]int, 5) 

In summary, reach for new() when you specifically need a pointer to a zero-initialized value of a non-collection type. For most struct initialization, prefer &Type{} for clarity, and always use make() for slices, maps, and channels.