How to properly init structs in Go inside slices without constructors

Issue

Go doesn’t have constructors so I’m wondering how you would properly initialize a struct inside a slice. I have trouble believing that the answer would be to initialize and copy all the structs twice?

package main

import "fmt"

// minQueueLen is smallest capacity that queue may have.
// Must be power of 2 for bitwise modulus: x % n == x & (n - 1).
const minQueueLen = 16

type Queue[T any] struct {
    buf []T
}

func New[T any]() *Queue[T] {
    return &Queue[T]{
        buf: make([]T, minQueueLen),
    }
}

type SomeStruct struct {
    q Queue[int]
}

func main() {
    someSlice := make([]SomeStruct, 10)

    // Now buf is the wrong size because we didn't
    // get to init it with the proper constructor.
    // It would be very wasteful to initialize this
    // struct twice (100s of thousands or more).

    fmt.Println("Size of a buf: ", len(someSlice[0].q.buf))
}

Here is an example where the buffer of the queue must be a power of 2.

Solution

You never really initialized it. Allocating a slice simply allocates the space, but does not initialize individual elements. Once you have the slice, you can loop through it and inialize:

func main() {
    someSlice := make([]SomeStruct, 10)

    for i:=range someSlice {
       someSlice[i].q=*New[int]()
    }

    fmt.Println("Size of a buf: ", len(someSlice[0].q.buf))
}

You can also do:

func (s *SomeStruct) Init()  {
    s.q=Queue[int]{
        buf: make([]int, minQueueLen),
    }
}


func main() {
    someSlice := make([]SomeStruct, 10)

    for i:=range someSlice {
       someSlice[i].Init()
    }

    fmt.Println("Size of a buf: ", len(someSlice[0].q.buf))
}

Answered By – Burak Serdar

Answer Checked By – Cary Denson (GoLangFix Admin)

Leave a Reply

Your email address will not be published.