답변:
당신이 할 수있는 일 make
이 다른 방법으로 할 수 없어 :
정당화하기가 조금 더 어렵습니다 new
. 가장 쉬운 것은 비 복합 유형에 대한 포인터를 만드는 것입니다. 아래의 두 기능은 동일합니다. 하나는 조금 더 간결합니다.
func newInt1() *int { return new(int) }
func newInt2() *int {
var i int
return &i
}
m := map[string]int{}
대신 m := make(map[string]int)
? 크기를 미리 할당 할 필요가 없습니다.
Go에는 여러 가지 메모리 할당 및 값 초기화 방법이 있습니다.
&T{...}
, &someLocalVar
, new
,make
복합 리터럴을 만들 때 할당이 발생할 수도 있습니다.
new
정수와 같은 값을 할당하는 데 사용할 수 있습니다 &int
.
new(Point)
&Point{} // OK
&Point{2, 3} // Combines allocation and initialization
new(int)
&int // Illegal
// Works, but it is less convenient to write than new(int)
var i int
&i
의 차이 new
와는 make
다음의 예를 보면 알 수있다 :
p := new(chan int) // p has type: *chan int
c := make(chan int) // c has type: chan int
Go에 new
and make
가 없지만 내장 기능 이 있다고 가정합니다 NEW
. 그런 다음 예제 코드는 다음과 같습니다.
p := NEW(*chan int) // * is mandatory
c := NEW(chan int)
는 *
필수가 될 것입니다 그래서 :
new(int) --> NEW(*int)
new(Point) --> NEW(*Point)
new(chan int) --> NEW(*chan int)
make([]int, 10) --> NEW([]int, 10)
new(Point) // Illegal
new(int) // Illegal
예, 단일 내장 기능으로 병합 new
및 통합 make
할 수 있습니다. 그러나 단일 내장 기능이 내장 된 두 기능을 갖는 것보다 새로운 Go 프로그래머에게 더 많은 혼란을 야기 할 가능성이 있습니다.
위의 모든 사항을 고려하면 더 적절 new
하고 make
분리 된 상태로 유지됩니다.
int
생성 된 인스턴스임을 보여줍니다 .
make(Point)
및 make(int)
그 마지막 두 줄?
make
함수는 slice, map 또는 chan 유형의 객체 만 할당하고 초기화합니다. 처럼 new
첫 번째 인수는 유형입니다. 그러나 크기에 대한 두 번째 주장이 필요할 수도 있습니다. new와 달리 make의 반환 유형은 포인터의 유형이 아니라 인수의 유형과 동일합니다. 그리고 할당 된 값이 초기화됩니다 (새로운 것과 같이 0으로 설정되지 않음). 그 이유는 slice, map 및 chan이 데이터 구조이기 때문입니다. 초기화해야합니다. 그렇지 않으면 사용할 수 없습니다. 이것이 new ()와 make ()가 달라야하는 이유입니다.
Effective Go의 다음 예는 매우 명확합니다.
p *[]int = new([]int) // *p = nil, which makes p useless
v []int = make([]int, 100) // creates v structure that has pointer to an array, length field, and capacity field. So, v is immediately usable
new([]int)
, 그것은 단지 [] int에 대한 메모리를 할당하지만 초기화하지 않기 때문에 단지 반환 nil
한다; 사용할 수 없기 때문에 메모리에 대한 포인터가 아닙니다. make([]int)
사용할 수 있도록 할당하고 초기화 한 다음 주소를 반환하십시오.
new(T)
- 메모리를 할당하고, 집합에 그것은 제로 값 유형에 대한 T ..
이다 ..that 0
대해 INT , ""
위한 문자열 과 nil
참조 타입 (위한 슬라이스 , 지도 , 찬 )
참조 유형은 일부 단지 포인터 참고 것을 기본 데이터 구조 , 생성되지 않습니다 에 의해 new(T)
의 경우 : 예 슬라이스 , 기본 배열이 생성되지 않습니다 따라서, new([]int)
아무것도 포인터를 반환
make(T)
-참조 된 데이터 유형 ( slice , map , chan )에 메모리를 할당 하고 기본 데이터 구조를 초기화 합니다.
예 : slice의 경우 지정된 길이와 용량으로 기본 배열 이 생성됩니다.
C와 달리 배열은 Go!의 기본 유형입니다.
그 말은 :
make(T)
복합 리터럴 구문처럼 동작
new(T)
처럼 행동한다 var
(변수가 초기화되지 않은 경우)
func main() {
fmt.Println("-- MAKE --")
a := make([]int, 0)
aPtr := &a
fmt.Println("pointer == nil :", *aPtr == nil)
fmt.Printf("pointer value: %p\n\n", *aPtr)
fmt.Println("-- COMPOSITE LITERAL --")
b := []int{}
bPtr := &b
fmt.Println("pointer == nil :", *bPtr == nil)
fmt.Printf("pointer value: %p\n\n", *bPtr)
fmt.Println("-- NEW --")
cPtr := new([]int)
fmt.Println("pointer == nil :", *cPtr == nil)
fmt.Printf("pointer value: %p\n\n", *cPtr)
fmt.Println("-- VAR (not initialized) --")
var d []int
dPtr := &d
fmt.Println("pointer == nil :", *dPtr == nil)
fmt.Printf("pointer value: %p\n", *dPtr)
}
프로그램을 실행
-- MAKE --
pointer == nil : false
pointer value: 0x118eff0 # address to underlying array
-- COMPOSITE LITERAL --
pointer == nil : false
pointer value: 0x118eff0 # address to underlying array
-- NEW --
pointer == nil : true
pointer value: 0x0
-- VAR (not initialized) --
pointer == nil : true
pointer value: 0x0
추가 읽기 :
https://golang.org/doc/effective_go.html#allocation_new
https://golang.org/doc/effective_go.html#allocation_make
당신은 필요한 make()
채널과지도를 만들기 위해 (그리고 조각을, 그러나 그 너무 배열을 만들 수 있습니다). 대체 할 방법이 없으므로 make()
사전에서 제거 할 수 없습니다 .
에 관해서는 new()
, 나는 어떤 이유를 모르는 즉석 당신이 왜 필요 를 당신은 구조체 구문을 사용할 수 있습니다 때. 그래도 고유 한 의미 론적 의미를 갖습니다. "모든 필드가 0으로 초기화 된 구조체를 생성하여 반환합니다"는 유용합니다.
외에도 모든에서이 설명 효과적인 이동 , 주요 차이점을 사이 new(T)
와&T{}
후자는 명시 적으로 힙 할당을 수행하는 것입니다. 그러나 이는 구현에 따라 다르므로 변경 될 수 있습니다.
비교 make
하려면 new
두 개의 완전히 다른 기능을 수행 할 때 약간의 의미가 있습니다. 그러나 이것은 링크 된 기사에서 자세히 설명됩니다.
&T{}
명시 적으로 힙 할당을 수행 한다는 주장 은 사양의 내용을 기반으로하지 않는 AFAIK입니다. 실제로 나는 탈출 분석이와 같은 방식으로 가능한 한 항상 * T를 스택에 유지한다고 생각 new(T)
합니다.