6

Using NEW, instead of MAKE, to create slice

 3 years ago
source link: https://dev.to/freakynit/using-new-instead-of-make-to-create-slice-17bl
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Nitin Bansal

Posted on Nov 28

Using NEW, instead of MAKE, to create slice

#go

As we know, slices in golang are reference types, and hence, need make to initialize them.

func main() {
    a := make([]int32, 0)
    a = append(a, 10, 20, 30)
    fmt.Println(len(a), cap(a), reflect.ValueOf(a).Kind())
}
>>> 3 4 slice
Enter fullscreen modeExit fullscreen mode

But, can we use new to make slices? It's meant to be used for value types only. So how can it work here??

Let's see

func main() {
    a := new([]int32)
}
Enter fullscreen modeExit fullscreen mode

Does this↑ work? Yes. It does. So what is the difference?

The difference is that this gives you a pointer, as is the case anytime you use new. Thus to actually use it, you have to dereference it everytime.

Example:

func main() {
    a := new([]int32)
    *a = append(*a, 10, 20, 30)
    fmt.Println(len(*a), cap(*a), reflect.ValueOf(*a).Kind())
}
>>> 3 4 slice
Enter fullscreen modeExit fullscreen mode

Another simple change you can do is to dereference it immediately after creation. This will save you the effort of dereferencing it every other time.

func main() {
    a := *new([]int32)
    a = append(a, 10, 20, 30)
    fmt.Println(len(a), cap(a), reflect.ValueOf(a).Kind())
}
>>> 3 4 slice
Enter fullscreen modeExit fullscreen mode

There's another important concept:

Every time you append to a slice, it gives you a new slice with a different address (though it points to same underlying array)

Let's see this with same example:

func main() {
    a := make([]int32, 0)
    fmt.Printf("%p\n", a)

    a = append(a, 10, 20, 30)
    fmt.Printf("%p\n", a)

    a = append(a, 10, 20, 30)
    fmt.Printf("%p\n", a)

    fmt.Println(len(a), cap(a), reflect.ValueOf(a).Kind())
}
>>> 0x116bea0
>>> 0xc0000220e0
>>> 0xc00001c100
>>> 6 8 slice
Enter fullscreen modeExit fullscreen mode

You see, all 3 addresses are different.

But, can we keep the addresses same even after append? Well yes!! It's here your NEW approach comes into place. See this:

func main() {
    a := new([]int32)
    fmt.Printf("%p\n", a)

    *a = append(*a, 10, 20, 30)
    fmt.Printf("%p\n", a)

    *a = append(*a, 10, 20, 30)
    fmt.Printf("%p\n", a)

    fmt.Println(len(*a), cap(*a), reflect.ValueOf(*a).Kind())
}
>>> 0xc00011c030
>>> 0xc00011c030
>>> 0xc00011c030
>>> 6 8 slice
Enter fullscreen modeExit fullscreen mode

You see? All 3 addresses remain same!!!

That's all folks for now?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK