'go1.18 generics cannot use *bytes.Reader as io.Reader

Attempting to map a slice of []byte to a slice of []*byte.Reader for use in mapping to Decode images results in cannot use jpeg.Decode (value of type func(r io.Reader) (image.Image, error)) as func(item *bytes.Reader) (image.Image, error) with go1.18 using generics

package main

import (
    "bytes"
    "fmt"
    "image"
    "image/jpeg"
    "log"
)

func main() {

    imagesBytes := [][]byte{
        []byte("test1"),
        []byte("test2"),
    }

    jpeg.Decode(bytes.NewReader(imagesBytes[0])) // works

    readers := Map(imagesBytes, bytes.NewReader)
    images, err := MapWithErr(readers, jpeg.Decode) // cannot use jpeg.Decode (value of type func(r io.Reader) (image.Image, error)) as func(item *bytes.Reader) (image.Image, error) value in argument to MapWithErr[*bytes.Reader, image.Image]compilerIncompatibleAssign
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(images)

}

func MapWithErr[T1 any, T2 any](items []T1, predicate func(item T1) (T2, error)) ([]T2, error) {
    output := make([]T2, len(items))

    for idx, item := range items {
        o, err := predicate(item)
        if err != nil {
            output = nil
            return output, err
        }

        output[idx] = o
    }

    return output, nil
}

func Map[T1 any, T2 any](items []T1, predicate func(item T1) T2) []T2 {
    output := make([]T2, len(items))

    for idx, item := range items {
        output[idx] = predicate(item)
    }

    return output
}

Why is it that I can directly pass a *bytes.Reader into jpeg.Decode() but when mapping and using generics, it doesn't work?



Solution 1:[1]

Because the type of acceptable parameter (io.Reader) in the jpeg.Decode() function is interface type And if you output bytes.NewReader function and you pass a type of *byte.Reader to the jpeg.Decode () function, there will be no problem But the second parameter in the MapWithErr function is of the function type, not the interface, and now the input of this parameter must be fully compatible with the received function and its parameters. In other words:

*Bytes.Reader and io.Reader types is not equal only *Bytes.Reader can be converted to io.Reader.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mohammad Abbasi