小能豆

Cannot use struct as the type struct {...}

go

I have this code:

type Iterable[T any] struct {
    Val  T
    End  T
    Next func() (bool, T)
}

func acceptStructWithNext[T any](r struct{ Next func() (bool, T) }) {
    fmt.Println(r)
}

func main() {

    iterable := Iterable[int]{
        Val: 0,
        End: 100,
        Next: func() (bool, int) {
            return true, 0
        },
    }

    acceptStructWithNext[int](iterable) // error is here

}

I get this compile error:

Cannot use ‘iterable’ (type Iterable[int]) as the type struct {…}

I thought structural typing was suppose to allow this type of thing - where did I go wrong?


阅读 44

收藏
2023-12-18

共1个答案

小能豆

The error you’re encountering is due to the fact that Go has a strong static type system, and it doesn’t support structural typing in the way you are trying to use it.

In your code, Iterable[int] is a distinct type from the anonymous struct used in acceptStructWithNext[int](iterable). Even though the structure of iterable matches the fields and methods of the anonymous struct, they are not considered the same type in Go’s type system.

To achieve what you want, you can define an interface with the necessary methods and use that interface in the acceptStructWithNext function:

type Iterator[T any] interface {
    Next() (bool, T)
}

type Iterable[T any] struct {
    Val  T
    End  T
    Next func() (bool, T)
}

func (it *Iterable[T]) Next() (bool, T) {
    return it.Next()
}

func acceptIterator[T any](it Iterator[T]) {
    fmt.Println(it)
}

func main() {
    iterable := Iterable[int]{
        Val:  0,
        End:  100,
        Next: func() (bool, int) { return true, 0 },
    }

    acceptIterator(&iterable)
}

In this example, I introduced an Iterator interface with a Next method. I also modified the Iterable type to have a method Next that matches the interface. The acceptIterator function now accepts anything that implements the Iterator interface.

Note that I changed the receiver type of the Next method to be a pointer receiver (func (it *Iterable[T]) Next() (bool, T)) to match the convention for methods that modify the receiver. If your use case requires non-pointer receivers, you can adjust accordingly.

2023-12-18