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.