Initializing generic slice with size inside a struct

74 views Asked by At

I'm trying to build a LIFO stack. I've created a Stack[T any] interface and a dynamicStack[T any] struct. dynamicStack has a data []T field and an index int field. When a dynamicStack is created, I want data to be initialized empty, of fixed size 1 and type T. Statement comes up: "cannot use [0]T{} (value of type [0]T) as []T value in assignment" when I try to do so.

type Stack[T any] interface {
    IsEmpty() bool
    SeeTop() T
    AddToStack(T)
    Unstack() T
}
type dynamicStack[T any] struct {
    data    []T
    index int
}
func CreateDynamicStack[T any]() Stack[T] {
    s := new(dynamicStack[T])
    s.data = [0]T{} // Problem
    s.index = 0
    return s
}

I've tried using const instead of "0", different sizes and even initializing the array as non-empty but nothing works.

I'm not trying to use append() method and I need a fixed size array as my plan is to resize the array whenever it's full or whenever it's half empty.

Any ideas?

1

There are 1 answers

0
LeGEC On BEST ANSWER

s.data is a slice, you should initialize it as a slice :

s.data = make([]T, 0)

Actually, go handles a nil slice pretty much like an empty slice, so you don't even need to initialize s.data in your structure. See the example below for an illustration.


In go, there is a difference between a slice type []T and an array type [n]T.

For a detailed explanation of how slices and arrays behave, see this article by Andrew Gerrand:
Go Slices: usage and internals


// example of slice usage:
func testSlice() {
    var s []int

    fmt.Println("length:", len(s))
    for i, x := range s {
        fmt.Println("iterating:", i, x) // never executed, the slice is empty
    }

    newSlice := append(s, 1)  // a slice allocation happens here
    fmt.Println("result of append(s,1):", newSlice)

    emptySlice := make([]int, 0)

    // the only visible different thing is comparing to nil:
    if s == nil {
        fmt.Println("s is nil")
    }
    if emptySlice == nil {
        fmt.Println("emptySlice is nil") // not printed
    }

    // if you stick to checking the *length* of your slice, you will
    // have a consistent behavior:
    if len(s) == 0 {
        fmt.Println("s is empty")
    }
    if len(emptySlice) == 0 {
        fmt.Println("emptySlice is empty")
    }
}

playground: https://go.dev/play/p/kB1g2Iq-n6u