[英]Assert interface to its type
在一般情况下,我不能优雅地将图像的像素作为数组。
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
接口获取类型?
使用类似这样的类型开关可以简化你的大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
字段进行结构化)。
这是它的样子:
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)
}
测试它:
fmt.Println(getPix(&image.NRGBA{}))
fmt.Println(getPix(&image.RGBA{}))
type unknownImage struct{ image.Image }
fmt.Println(getPix(unknownImage{}))
输出(在Go Playground上试试):
[] <nil>
[] <nil>
[] unknown image type main.unknownImage
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.