Golang make function
last modified May 8, 2025
This tutorial explains how to use the make
built-in function in Go.
We'll cover slice, map, and channel creation with practical examples.
The make function allocates and initializes objects of type slice,
map, or channel. Unlike new
, which returns a pointer, make
returns an initialized value ready to use.
In Go, make
is essential for creating complex data structures with
specific initial capacities. It ensures proper initialization of internal state.
Creating a slice with make
The simplest use of make
creates a slice with specified length and
capacity. This example demonstrates basic slice creation.
Note: The capacity parameter is optional.
package main import "fmt" func main() { // Create slice with length 3 and capacity 5 nums := make([]int, 3, 5) fmt.Println("Slice:", nums) fmt.Println("Length:", len(nums)) fmt.Println("Capacity:", cap(nums)) // Append elements within capacity nums = append(nums, 4, 5) fmt.Println("After append:", nums) // Append beyond capacity nums = append(nums, 6) fmt.Println("After exceeding capacity:", nums) }
The slice is initialized with zero values for its length. Capacity determines when the underlying array needs reallocation. Appending beyond capacity causes automatic resizing.
Creating a map with make
We can create maps with initial capacity using make
. This example
shows map creation and basic operations.
package main import "fmt" func main() { // Create map with initial capacity userAges := make(map[string]int, 10) // Add elements userAges["Alice"] = 25 userAges["Bob"] = 30 userAges["Charlie"] = 28 fmt.Println("User ages:", userAges) // Check existence if age, exists := userAges["Bob"]; exists { fmt.Println("Bob's age:", age) } // Delete element delete(userAges, "Charlie") fmt.Println("After deletion:", userAges) }
The capacity hint helps optimize map performance by reducing rehashing. Maps dynamically grow regardless of initial capacity. Elements can be added, checked, and deleted.
Creating a buffered channel with make
make
creates channels with specified buffer size. This example shows
buffered channel operations.
package main import "fmt" func main() { // Create buffered channel with capacity 3 messages := make(chan string, 3) // Send messages without blocking messages <- "first" messages <- "second" messages <- "third" // Receive messages fmt.Println(<-messages) fmt.Println(<-messages) fmt.Println(<-messages) // Close channel close(messages) }
Buffered channels allow sending multiple values without blocking. The channel holds values until received. Closing is optional but recommended when done.
Slice with make and copy
make
can create slices for copying data. This example demonstrates
efficient data copying.
package main import "fmt" func main() { original := []int{1, 2, 3, 4, 5} // Create slice with exact needed capacity copySlice := make([]int, len(original)) // Copy elements copied := copy(copySlice, original) fmt.Println("Original:", original) fmt.Println("Copied:", copySlice) fmt.Println("Elements copied:", copied) // Modify copy copySlice[0] = 100 fmt.Println("After modification:") fmt.Println("Original:", original) fmt.Println("Copied:", copySlice) }
Creating slices with exact capacity avoids unnecessary allocations. The copy
function returns number of elements copied. Modifying the copy doesn't affect the original.
Map with make for concurrent access
make
creates maps that can be used with sync primitives. This example
shows thread-safe map access.
package main import ( "fmt" "sync" ) type SafeMap struct { sync.RWMutex data map[string]int } func NewSafeMap() *SafeMap { return &SafeMap{ data: make(map[string]int), } } func (sm *SafeMap) Set(key string, value int) { sm.Lock() defer sm.Unlock() sm.data[key] = value } func (sm *SafeMap) Get(key string) (int, bool) { sm.RLock() defer sm.RUnlock() val, exists := sm.data[key] return val, exists } func main() { sm := NewSafeMap() var wg sync.WaitGroup // Concurrent writes for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() key := fmt.Sprintf("key%d", i) sm.Set(key, i) }(i) } wg.Wait() // Read values for i := 0; i < 10; i++ { key := fmt.Sprintf("key%d", i) if val, exists := sm.Get(key); exists { fmt.Printf("%s: %d\n", key, val) } } }
The SafeMap
wrapper provides thread-safe access to a map created with
make
. Mutexes protect concurrent access. This pattern is common in
concurrent Go programs.
Source
This tutorial covered the make
function in Go with practical
examples of slice, map, and channel creation.
Author
List all Golang tutorials.