问题
package main
import "fmt"
func main() {
p := new(map[string]int)
m := make(map[string]int)
m["in m"] = 2
(*p)["in p"] = 1
fmt.Println(m)
fmt.Println(*p)
}
The above code gives an error panic: assignment to entry in nil map
. If I print *p
before inserting pairs into it, the output is correct. It seems I just can't modify *p
?
回答1:
Both new
and make
are used to allocate memory in a program, but they work differently. new(T, args)
zeros memory and returns the memory address (a value of type *T
) but does not initialize that memory. make(T, args)
on the other hand initializes a value of type T
. A map need to be initialized because, while a map can be empty, there is still the structure of the map itself, which is non-zero and therefore needs to be initialized before use.
From Effective Go:
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.
回答2:
This is not directly an issue with new
keyword. You would get the same behavior, if you did not initialize your map, when declaring it with var
keyword, for example:
var a map[string]int
a["z"] = 10
The way to fix this is to initialize the map:
var a map[string]int
a = map[string]int{}
a["z"] = 10
And it works the same way, with new
keyword:
p := new(map[string]int)
*p = map[string]int{}
(*p)["in p"] = 1
The reason make(map[string]int)
does what you expect is that the map is declared and initialized.
Go Playground
来源:https://stackoverflow.com/questions/53799199/why-cant-i-initialize-a-map-with-new-in-go