# Demystifying new() and make() Functions in Go

Go (or Golang) is a modern, statically typed, compiled programming language designed for building scalable, concurrent, and efficient software. It comes with various built-in functions and features that help developers write concise and performant code. Among these functions are `new()` and `make()`, which might seem similar at first but serve different purposes and are crucial for memory allocation and data initialization in Go.

In this blog post, we will explore the differences between `new()` and `make()` functions and understand when and how to use them effectively.

## `new()` **and** `make()` Functions

Both `new()` and `make()` are built-in functions in Go, used to allocate memory. However, they are used for different data types and scenarios:

1. `new()` function:
    
    * `new()` is used to allocate memory for value types (e.g., integers, floats, structs) and returns a pointer to the newly allocated zeroed value.
        
    * It takes a single argument, which is a type, and returns a pointer to that type.
        
2. `make()` function:
    
    * `make()` is used to create and initialize slices, maps, and channels, which are reference types in Go.
        
    * It takes two or three arguments, depending on the type, and returns an initialized (not zeroed) value ready for use.
        

## **Understanding** `new()` Function

The syntax of the `new()` function is straightforward as shown below.

```go
func new(Type) *Type
```

Here, `Type` represents the type of the value we want to allocate memory for. Let's see an example of how to use `new()`

In this example, we create a new instance of the `Person` struct using `new()` and then assign values to its fields using the pointer.

```go
package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    // Using new() to allocate memory for a Person struct
    p := new(Person)

	fmt.Printf("%T\n", p)

    // Accessing struct fields using the pointer
    p.Name = "Alice"
    p.Age = 30

    // Displaying the values
    fmt.Println("Name:", p.Name)
    fmt.Println("Age:", p.Age)
}
```

This program will produce an output as shown below

```go
> go run main.go
*main.Person
Name: Alice
Age: 30
```

## **Understanding** `make()` Function

The syntax of the `make()` function varies depending on the type it is used with

***For Slices***

```go
func make([]Type, len, cap) []Type
```

* `Type`: The type of elements the slice will hold.
    
* `len`: The initial length of the slice.
    
* `cap`: The capacity of the slice, which is optional and used to specify the underlying array's capacity. If not provided, it defaults to the same value as the length.
    

Example of creating a slice using `make()`:

```go
package main

import "fmt"

func main() {
    // Using make() to create a slice of integers
    numbers := make([]int, 5, 10)

    // Displaying the slice's length, capacity, and values
    fmt.Println("Length:", len(numbers))
    fmt.Println("Capacity:", cap(numbers))
    fmt.Println("Values:", numbers)

    // Using make() to create a slice of integers
    numbersWithoutOptional := make([]int, 5)

    // Displaying the slice's length, capacity, and values
    fmt.Println("Length:", len(numbersWithoutOptional))
    fmt.Println("Capacity:", cap(numbersWithoutOptional))
    fmt.Println("Values:", numbersWithoutOptional)
}
```

This program will produce an output as below

```bash
> go run main.go
Length: 5
Capacity: 10
Values: [0 0 0 0 0]
Length: 5
Capacity: 5
Values: [0 0 0 0 0]
```

***For Maps***

```go
func make(map[KeyType]ValueType, initialCapacity int) map[KeyType]ValueType
```

* `KeyType`: The type of keys in the map.
    
* `ValueType`: The type of values associated with the keys.
    
* `initialCapacity`: The initial capacity of the map. This is optional but can be used to optimize performance when the number of elements is known in advance.
    

Example of creating a map using `make()`

```go
package main

import "fmt"

func main() {
    // Using make() to create a map of string keys and int values
    scores := make(map[string]int)

    // Adding values to the map
    scores["Alice"] = 95
    scores["Bob"] = 87

    // Displaying the map
    fmt.Println("Scores:", scores)
}
```

```go
> go run main.go
Scores: map[Alice:95 Bob:87]
```

***For Channels***

```bash
func make(chan Type, capacity int) chan Type
```

* `Type`: The type of values that can be sent and received through the channel.
    
* `capacity`: The buffer size of the channel. If set to 0, the channel is unbuffered.
    

Example of creating a channel using `make()`

```go
package main

import (
    "fmt"
    "time"
)

func main() {
    // Using make() to create an unbuffered channel of integers
    ch := make(chan int)

    // Sending data into the channel using a goroutine
    go func() {
        for i := 1; i <= 5; i++ {
            ch <- i
            time.Sleep(time.Second) // Simulating some work before sending the next value
        }
        close(ch)
    }()

    // Receiving data from the channel
    for num := range ch {
        fmt.Println("Received:", num)
    }
}
```

```bash
> go run main.go
Received: 1
Received: 2
Received: 3
Received: 4
Received: 5
```

## **Conclusion**

In this blog post, we have demystified the `new()` and `make()` functions in Go and explained their differences and use cases. To summarize:

* Use `new()` to allocate memory for value types and obtain a pointer to the zeroed value.
    
* Use `make()` to create and initialize slices, maps, and channels (reference types) with their respective types and initial capacities.
    

Understanding the distinctions between `new()` and `make()` is crucial for efficient memory allocation and data initialization in Go. Properly applying these functions will lead to cleaner and more optimized code in your Golang projects. Happy coding!
