Home >Backend Development >Golang >Generic functions that accept channels and slices

Generic functions that accept channels and slices

PHPz
PHPzforward
2024-02-06 08:36:10807browse

Generic functions that accept channels and slices

Question content

I am trying to write a generic function in golang that will search for values ​​in slices and channels in a similar way. Here is an example:

// minof returns the smallest number found among the channel / slice contents
func minof[t chan int | []int](input t) (result int) {
    for _, value := range input {
        if result > value {
            result = value
        }
    }

    return
}

But I get the following compilation error: cannot range over input (Variable of type t is bound by chan int|[]int) (t has no core type) .

I try to create a generic interface like this:

type Rangable interface {
    chan int | []int
}

// MinOf returns the smallest number found among the channel / slice contents
func MinOf[T Rangable](input T) (result int) {
    for _, value := range input {
        if result > value {
            result = value
        }
    }

    return
}

Although, the error has been changed to cannot range over input (variable of type t subject to rangable) (t has no core type) It remains basically the same...

Is there any way to solve this task using generics or channels and the slice cannot be "converted" to the same core type?

Thank you for any suggestions and ideas!


Correct answer


You can't do that.

range The expression must begin with a core type. Unions with terms of different types have no core type because there is no common underlying type.

You can also intuitively see why

range requires a core type: the semantics of slice and channel ranges are different.

  1. Ranging on a channel may be a blocking operation, ranging on a slice is not

  2. Iteration variables are different

  3. for i, item := range someslice {}
For slices,

i is an index of type int and item is the type of the slice element.

for item := range somechan {}

For channels,

item is the type of the chan element, and this is the only possible scope variable.

The best you can have is a type switch:

func MinOf[T any, U chan T | []T](input U) (result int) {
    switch t := any(input).(type) {
    case chan T:
        // range over chan
    case []T:
        // range over slice
    }
    return
}

But again, the behavior of this function (blocking vs. non-blocking) depends on the type, and it's not clear what advantage you can gain by using generics here.

The above is the detailed content of Generic functions that accept channels and slices. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete