$ go doc
package builtin // import "builtin"

func new(Type) *Type
    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.

$ go doc builtin.make
package builtin // import "builtin"

func make(t Type, size ...IntegerType) Type
    The make built-in function allocates and initializes an object of type
    slice, map, or chan (only). Like new, the first argument is a type, not a
    value. Unlike new, make's return type is the same as the type of its
    argument, not a pointer to it. The specification of the result depends on
    the type:

        Slice: The size specifies the length. The capacity of the slice is
        equal to its length. A second integer argument may be provided to
        specify a different capacity; it must be no smaller than the
        length. For example, make([]int, 0, 10) allocates an underlying array
        of size 10 and returns a slice of length 0 and capacity 10 that is
        backed by this underlying array.
        Map: An empty map is allocated with enough space to hold the
        specified number of elements. The size may be omitted, in which case
        a small starting size is allocated.
        Channel: The channel's buffer is initialized with the specified
        buffer capacity. If zero, or the size is omitted, the channel is
  • func new(Type) *Type
  • func make(t Type, size ...IntegerType) Type

newmake 的区别

  1. new 没有类型限制,make 只能用来分配和初始化 slice,map,chan。
  2. new 返回指针,make 返回引用(引用类型的值)。
  3. new 会将分配的空间置零(对应类型的零值),make 则可以类型初始化,比如 slice 的长度和容量。
package main

import "fmt"

type User struct {
    Name string

type Addr struct{}

func main() {
    user1 := new(User)
    user2 := new(User)
    fmt.Printf("%#v (%p) %d\n", user1, user1, &user1)
    fmt.Printf("%#v (%p) %d\n", user2, user2, &user2)
    fmt.Printf("user1 == user2 : %#v\n", user1 == user2)

    addr1 := new(Addr)
    addr2 := new(Addr)
    fmt.Printf("%#v (%p) %d\n", addr1, addr1, &addr1)
    fmt.Printf("%#v (%p) %d\n", addr2, addr2, &addr2)
    fmt.Printf("addr1 == addr2 : %#v\n", addr1 == addr2)
&main.User{Name:""} (0xc00006a250) 824633745448
&main.User{Name:""} (0xc00006a260) 824633745456
user1 == user2 : false
&main.Addr{} (0xf61438) 824633745472
&main.Addr{} (0xf61438) 824633745480
addr1 == addr2 : true

注意上面这一点,空 struct 多次 new 出的指针完全相同。暂时没有想明白这样设计的好处。