IT

왜 내가 () 또는 new ()를 만들 것입니까?

lottoking 2020. 5. 17. 11:08
반응형

왜 내가 () 또는 new ()를 만들 것입니까?


도입 문서 사이의 차이를 설명하는 많은 단락을 할애 new()하고 make()있지만, 실제로는, 당신은 지역의 범위 내에서 객체를 생성하고 반환 할 수 있습니다.

할당 자 쌍을 왜 사용 하시겠습니까?


당신이 할 수있는 것들 make다른 방법으로는 할 수 없습니다 :

  • 채널 만들기
  • 공간이 미리 할당 된 맵 만들기
  • 공간이 미리 할당되거나 len! = cap로 슬라이스를 만듭니다.

정당화하기가 조금 더 어렵습니다 new. 가장 쉬운 것은 비 복합 유형에 대한 포인터를 만드는 것입니다. 아래의 두 기능은 동일합니다. 하나는 조금 더 간결합니다.

func newInt1() *int { return new(int) }

func newInt2() *int {
    var i int
    return &i
}

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에 newand 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분리 된 상태로 유지됩니다.


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

당신은 필요한 make()채널과지도를 만들기 위해 (그리고 조각을, 그러나 그 너무 배열을 만들 수 있습니다). 대체 할 방법이 없으므로 make()사전에서 제거 할 수 없습니다 .

As for new(), I don't know of any reason offhand why you need it when you can use struct syntax. It does have a unique semantic meaning though, which is "create and return a struct with all fields initialized to their zero value", which can be useful.


Apart from everything explained in Effective Go, The main difference between new(T) and &T{} is that the latter explicitly performs a heap allocation. However it should be noted that this is implementation dependent and thus may be subject to change.

Comparing make to new makes little sense as the two perform entirely different functions. But this is explained in detail in the linked article.


new(T) : it returns a pointer to type T a value of type *T, it allocates and zeroes the memory. new(T) is equivalent to &T{}.

make(T) : it returns an initialized value of type T, It allocates and initializes the memory. Its used for slices, map and channels.


  • new(T) - Allocates memory, and sets it to the zero value for type T..
    ..that is 0 for int, "" for string and nil for referenced types (slice, map, chan)

    Note that referenced types are just pointers to some underlying data structures, which won't be created by new(T)
    Example: in case of slice, the underlying array won't be created, thus new([]int) returns a pointer to nothing

  • make(T) - Allocates memory for referenced data types (slice, map, chan), plus initializes their underlying data structures

    Example: in case of slice, the underlying array will be created with the specified length and capacity
    Bear in mind that, unlike C, an array is a primitive type in Go!


That being said:

  • make(T) behaves like composite-literal syntax
  • new(T) behaves like var (when the variable is not initialized)

    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)
    }
    

    Run the program

    -- 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
    

    Further reading:
    https://golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make

  • 참고URL : https://stackoverflow.com/questions/9320862/why-would-i-make-or-new

    반응형