목차
많은 친구들이 Golang을 처음 접했을 때 메모리를 할당하는 두 가지 기능이있는 이유를 이해하지 못했습니다 : new와 make. 속담처럼 : 존재는 합리적입니다. 둘의 차이점에 대해 자세히 설명하겠습니다.
하나, 새로운
먼저 함수 선언을 살펴보십시오.
func new(Type) *Type
new는 메모리를 할당하는 데 사용되는 Golang의 내장 함수입니다. 첫 번째 매개 변수는 유형이고 반환 값은 유형의 포인터입니다. 값은 "0"(유형에 해당하는 0 값, int는 0으로 초기화되고 bool은 false로 초기화됩니다.)
예 :
package main
import "fmt"
func main() {
id := new(int)
name := new(string)
flag := new(bool)
fmt.Printf("id type: %T value: %v\n", id, *id)
fmt.Printf("name type: %T value: %v\n", name, *name)
fmt.Printf("flag type: %T value: %v\n", flag, *flag)
}
산출:
id type: *int value: 0
name type: *string value:
flag type: *bool value: false
위 예제에서 알 수 있듯이 초기화 된 "zero"값은 타입에 따라 다르며 정수는 0으로 초기화되고 문자열은 빈으로 초기화되며 bool 타입은 false로 초기화됩니다.
둘, make
먼저 함수 선언을 살펴보십시오.
func make(t Type, size ...IntegerType) Type
make는 Golang의 내장 함수로 객체의 슬라이스, 맵, 채널 유형 을 할당 하고 초기화하는 데만 사용되며 세 유형 모두 구조입니다. 반환 값은 포인터가 아닌 형식입니다.
슬라이스 소스 코드 구조 :
type slice struct {
array unsafe.Pointer //指针
len int //长度
cap int //容量
}
맵 소스 코드 구조 :
// A header for a Go map.
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler's definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
채널 소스 구조 :
type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
// lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex
}
예 :
package main
import "fmt"
func main() {
//map
fmt.Println("map:")
var nameId = make(map[string]int, 0)
fmt.Printf("nameId \ntype: %#v\n", nameId)
nameId["Golang"] = 1
nameId["C++"] = 2
nameId["PHP"] = 3
for name, id := range nameId {
fmt.Printf("name = %v, id = %v\n", name, id)
}
// slice
var hobby = make([]string, 2, 100) // 其中 2是长度,100是容量
hobby[0] = "打篮球"
hobby[1] = "乒乓球"
fmt.Println("\nslice:")
fmt.Printf("length = %v caps = %v\n", len(hobby), cap(hobby))
for _, name := range hobby {
fmt.Println(name)
}
// channel
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 8
close(ch)
fmt.Println("\nchannel:")
for val := range ch { // 遍历数据
fmt.Println(val)
}
}
산출:
[root@localhost test]# go run main.go
map:
nameId
type: map[string]int{}
name = Golang, id = 1
name = C++, id = 2
name = PHP, id = 3
slice:
length = 2 caps = 100
打篮球
乒乓球
channel:
1
2
8
[root@localhost test]#
셋, 새로운 것과 만드는 것의 차이
1. new와 make는 모두 메모리 할당에 사용됩니다.
2. 모두 new 및 make 메모리를 힙에 할당합니다.
3. New는 포인터 유형에 대한 메모리를 할당하고 반환 값은 할당 유형의 포인터이며 New는 슬라이스, 맵 및 채널에 대한 메모리를 직접 할당 할 수 없습니다.
4. Make는 슬라이스, 맵 및 채널의 초기화에만 사용되며 반환 값은 포인터가 아닌 유형 자체입니다.