GO 内存分配new和make的区别
来源:互联网 发布:java手游飞机 编辑:程序博客网 时间:2024/06/04 19:49
func new
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.
func make
func make(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 isequal to its length. A second integer argument may be provided tospecify a different capacity; it must be no smaller than thelength, so make([]int, 0, 10) allocates a slice of length 0 andcapacity 10.Map: An empty map is allocated with enough space to hold thespecified number of elements. The size may be omitted, in which casea small starting size is allocated.Channel: The channel's buffer is initialized with the specifiedbuffer capacity. If zero, or the size is omitted, the channel isunbuffered.
1、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 *SyncedBuffervar v SyncedBuffer // type SyncedBuffer
2、Constructors and composite literals(复合字面量)
Sometimes the zero value isn't good enough and an initializing constructor is necessary, as in this example derived from packageos
.func NewFile(fd int, name string) *File { if fd < 0 { return nil } f := new(File) f.fd = fd f.name = name f.dirinfo = nil f.nepipe = 0 return f}There's a lot of boiler plate in there. We can simplify it using a composite literal, which is an expression that creates a new instance each time it is evaluated.
func NewFile(fd int, name string) *File { if fd < 0 { return nil } f := File{fd, name, nil, 0} return &f}Note that, unlike in C, it's perfectly OK to return the address of a local variable; the storage associated with the variable survives after the function returns. In fact, taking the address of a composite literal allocates a fresh instance each time it is evaluated, so we can combine these last two lines.
return &File{fd, name, nil, 0}The fields of a composite literal are laid out in order and must all be present. However, by labeling the elements explicitly as field
:
value pairs, the initializers can appear in any order, with the missing ones left as their respective zero values. Thus we could sayreturn &File{fd: fd, name: name}As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. The expressions
new(File)
and &File{}
are equivalent.Composite literals can also be created for arrays, slices, and maps, with the field labels being indices or map keys as appropriate.
a := [...]string{1: "no error", 2: "Eio", 3: "invalid argument"}
s := []string{1: "no error", 2: "Eio", 3: "invalid argument"}
m := map[int]string{1: "no error", 2: "Eio", 3: "invalid argument"}
3、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 usefulvar 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.- GO 内存分配new和make的区别
- Go中的make和new的区别
- go中new和make的区别?
- go中new和make的区别
- Go new和make的区别
- Go 语言中的 new() 和 make() 的区别
- Go 语言中的 new() 和 make() 的区别
- Go 语言中的 new() 和 make()的区别
- Go 语言中的 new() 和 make()的区别(转)
- go 中 make 与 new 的区别
- go语言的new和make
- new 和malloc 给变量分配内存的区别
- 动态内存分配- new/delete 和malloc/free的区别
- Go中的make和new
- go语言make()和new()
- Go内建函数(对于引用类型) new 和 make 的区别
- Golang中new和make的区别
- Golang中new和make的区别
- 数学期望(360)
- vi快捷键使用大全
- URL 统一资源定位符
- Serilizable/Externalizable/transient
- Xshell拖拽文件到linux(rz和sz命令用法详解)
- GO 内存分配new和make的区别
- centos 下无法使用lsof命令"-bash: lsof: command not found"
- 技术积累20170326
- 文章标题
- 随笔
- OpenCV python 学习笔记(九)
- java工厂模式和抽象工厂模式学习笔记
- dubbo进阶--基本概念
- IOS 关键字self,super,copy, retain, assign , readonly , readwrite, nonatomic、@synthesize、@property、@dyna