将接口声明为其类型

时间:2018-09-04 10:34:06

标签: go assertion go-interface

一般情况下,我无法正常获得图像的像素作为数组。

f, err := os.Open(imgPath)
check(err)
defer f.Close()
img, _, err := image.Decode(bufio.NewReader(f))
check(err)
pixels, err := getPixels(img)
check(err)
// Logic with pixels.

现在函数getPixels看起来像这样:

func getPixels(img image.Image) ([]uint8, error) {
    if i, ok := img.(*image.NRGBA); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.Alpha); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.Alpha16); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.CMYK); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.Gray); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.Gray16); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.NRGBA64); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.Paletted); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.RGBA); ok {
        return i.Pix, nil
    } else if i, ok := img.(*image.RGBA64); ok {
        return i.Pix, nil
    }
    return nil, fmt.Errorf("unknown image type %T", img)
}

但是我认为这很丑。 Golang知道图像的类型,我希望这样:

func getPixels(img image.Image) ([]uint8, error) {
    if i, ok := img.(eval(fmt.Sprintf("%T", img))); ok {
        return i.Pix, nil
    }
    return nil, fmt.Errorf("unknown image type %T", img)
}

我也不能断言reflect.TypeOf(img)。也许有一种方法可以从reflect.Type界面获取类型?

1 个答案:

答案 0 :(得分:6)

可以使用type switch来简化大型AppPhoenix.getInstance().restart(this)结构:

<div class="card">

                <div class="col-xs-12">
                            <a class="a_link" target="_blank" href="/storage/votes/-vote-14/mammals.jpg">
                            <img class=" pull-left img-medium-preview" src="/storage/votes/-vote-14/mammals.jpg" alt="Which is the tallest mammal?" width="423" height="280">
                        </a>


                    <div>
                        <h5 class="card-title">Which is the tallest mammal?</h5>

                        <p class="card-text">
                            Which is the tallest mammal lorem  ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod  tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim  veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea  commodo consequat. Duis aute irure dolor in reprehenderit in voluptate  velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint  occaecat cupidatat non proident, sunt in culpa qui officia deserunt  mollit anim id est laborum. lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                        </p>
                    </div>

                </div>

            </div>

您仍然必须列出所有可能的类型,但这更好。

由于所有图像实现都是具有名为if ... else的字段的结构指针,因此您可以使用反射来获取该字段。此实现将处理将来的图像实现,而无需进行任何更改(如果它们也将是带有func getPixels(img image.Image) ([]uint8, error) { switch i := img.(type) { case *image.NRGBA: return i.Pix, nil case *image.Alpha: return i.Pix, nil case *image.Alpha16: return i.Pix, nil case *image.CMYK: return i.Pix, nil // ... } return nil, fmt.Errorf("unknown image type %T", img) } 字段的结构)。

它是这样的:

Pix

测试:

Pix

输出(在Go Playground上尝试):

func getPix(img image.Image) ([]uint8, error) {
    v := reflect.ValueOf(img)
    if v.Kind() == reflect.Ptr {
        v = v.Elem()
    }

    if v.Kind() == reflect.Struct {
        pv := v.FieldByName("Pix")
        if pv.IsValid() {
            if pix, ok := pv.Interface().([]uint8); ok {
                return pix, nil
            }
        }
    }

    return nil, fmt.Errorf("unknown image type %T", img)
}
相关问题