新函数与未初始化变量的区别

What's the difference of new function and uninitialized variable? What's the advantage of both?

s := new(string) // *string
var s *string    // *string
var s string     // string

Is it only for simplicity the code? Because i think it's same

s := new(string) /* same as */ var s *string = &emptyString

first difference:

The built-in function new takes a type T, allocates storage for a variable of that type at run time

2nd difference: new initializes allocated string to empty string ("") and initializes pointer to the address of this string, but var ptr2 *string just initializes ptr2 to nil and do not allocates any string:

sample code A (with commented output):

ptr := new(string)               // *ptr has value "", ptr: static type *string
fmt.Println(len(*ptr))           // 0
fmt.Println(cap([]byte(*ptr)))   // 32
fmt.Printf("%T %q
", ptr, *ptr) // *string ""

sample code B (with commented output):

var ptr2 *string                // ptr2 has value nil, static type *string
fmt.Printf("%T %#[1]v
", ptr2) // *string (*string)(nil)
//fmt.Println(len(*ptr2)) // panic: runtime error: invalid memory address or nil pointer dereference
//fmt.Println(cap([]byte(*ptr2)))

sample code C (with commented output):

var str string                // str has value "", static type string
fmt.Println(len(str))         // 0
fmt.Println(cap([]byte(str))) // 32
fmt.Printf("%T %[1]q
", str) // string ""

Allocation:

The built-in function new takes a type T, allocates storage for a variable of that type at run time, and returns a value of type *T pointing to it. The variable is initialized as described in the section on initial values.

new(T)

For instance

type S struct { a int; b float64 }
new(S)

allocates storage for a variable of type S, initializes it (a=0, b=0.0), and returns a value of type *S containing the address of the location.

ref: https://golang.org/ref/spec

Allocation with new:

Go has two allocation primitives, the built-in functions new and make. They do different things and apply to different types, which can be confusing, but the rules are simple. Let's talk about new first. It's a built-in function that allocates memory, but unlike its namesakes in some other languages it does not initialize the memory, it only zeros it. That is, new(T) allocates zeroed storage for a new item of type T and returns its address, a value of type *T. In Go terminology, it returns a pointer to a newly allocated zero value of type T.

Since the memory returned by new is zeroed, it's helpful to arrange when designing your data structures that the zero value of each type can be used without further initialization. This means a user of the data structure can create one with new and get right to work. For example, the documentation for bytes.Buffer states that "the zero value for Buffer is an empty buffer ready to use." Similarly, sync.Mutex does not have an explicit constructor or Init method. Instead, the zero value for a sync.Mutex is defined to be an unlocked mutex.

The zero-value-is-useful property works transitively. Consider this type declaration.

type SyncedBuffer struct {
    lock    sync.Mutex
    buffer  bytes.Buffer
} Values of type SyncedBuffer are also ready to use immediately upon allocation or just declaration. In the next snippet, both p and v

will work correctly without further arrangement:

p := new(SyncedBuffer)  // type *SyncedBuffer
var v SyncedBuffer      // type  SyncedBuffer

Allocation with make: Back to allocation. The built-in function make(T, args) serves a purpose different from new(T). It creates slices, maps, and channels only, and it returns an initialized (not zeroed) value of type T (not *T). The reason for the distinction is that these three types represent, under the covers, references to data structures that must be initialized before use. A slice, for example, is a three-item descriptor containing a pointer to the data (inside an array), the length, and the capacity, and until those items are initialized, the slice is nil. For slices, maps, and channels, make initializes the internal data structure and prepares the value for use. For instance,

make([]int, 10, 100) 

allocates an array of 100 ints and then creates a slice structure with length 10 and a capacity of 100 pointing at the first 10 elements of the array. (When making a slice, the capacity can be omitted; see the section on slices for more information.) In contrast, new([]int) returns a pointer to a newly allocated, zeroed slice structure, that is, a pointer to a nil slice value. These examples illustrate the difference between new and make:

var p *[]int = new([]int)       // allocates slice structure; *p == nil; rarely useful
var v  []int = make([]int, 100) // the slice v now refers to a new array of 100 ints

// Unnecessarily complex:
var p *[]int = new([]int)
*p = make([]int, 100, 100)

// Idiomatic:
v := make([]int, 100)

Remember that make applies only to maps, slices and channels and does not return a pointer. To obtain an explicit pointer allocate with new or take the address of a variable explicitly.

ref: https://golang.org/doc/effective_go.html

This code:

var s *string

Simply declare "s" as a pointer to a string. In this case "s" is a nil pointer, this is the default value in golang for pointers.

This code:

s := new(string)

Also declare "s" as a pointer to a string, but this time the string is initialized. That means "s" is a non-nil pointer, and points to the default value for string in golang, an empty string.

See this playground