GoLang is a modern, statically typed, compiled programming language designed for building scalable, concurrent, and efficient software. It provides various built-in functions and features that help developers write concise and efficient code. Among them are the new()
and make()
functions, which may appear similar at first glance but serve different purposes in GoLang and are crucial for memory allocation and data initialization.
In this blog article, we will explore the differences between the new()
and make()
functions, and understand when and how to use them effectively.
new() and make()
new()
and make()
are both built-in functions in GoLang used for memory allocation. However, they are used for different data types and scenarios:
new() function
new()
is used to allocate memory for value types such as integers, floating-point numbers, and structs, and returns a pointer to the newly allocated zero value.
It takes a single parameter which is the type and returns a pointer to that type.
make() function
make()
is used to create and initialize slices, maps, and channels, which are reference types in GoLang.
It takes two or three parameters depending on the type and returns an initialized(non-zero value) that is ready to be used.
Understanding the new() function
The syntax for the new()
function is very simple, as shown below:
func new(Type) *Type
Here, Type represents the type of value for which we want to allocate memory. Let's look at an example of how to use new()
.
In this example, we use new()
to create a new instance of the Person struct and then assign values to its fields using pointers.
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)
}
The output would be
*main.Person
Name: Alice
Age: 30
Understanding the make() function
The syntax of the make()
function depends on the type it is used for.
For slices
func make([]Type, len, cap) []Type
- Type: The type of elements that 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 capacity of the underlying array. If not provided, it defaults to the same as the length.
Here's an example of creating a slice using make()
:
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)
}
The output would be
Length: 5
Capacity: 10
Values: [0 0 0 0 0]
Length: 5
Capacity: 5
Values: [0 0 0 0 0]
For map
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.
Here's an example of creating a map using make()
:
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)
}
The output would be
Scores: map[Alice:95 Bob:87]
For channel
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.
Here's an example of creating a channel using make()
:
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)
}
}
The output would be
Received: 1
Received: 2
Received: 3
Received: 4
Received: 5
Conclusion
In this blog article, we unraveled the mystery of the new()
and make()
functions in GoLang and explained their differences and use cases. To summarize:
- Use
new()
to allocate memory for value types and obtain a pointer to the zero value. - Use m
ake()
to create and initialize slices, maps, and channels(reference types), specifying their type and initial capacity.
Understanding the difference between new()
and make()
is crucial for efficient memory allocation and data initialization in GoLang. Using these functions correctly will result in cleaner and optimized code in your GoLang projects. Happy coding!