断言接口的类型

2024-01-11

在一般情况下,我无法优雅地将图像的像素作为数组获取。

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结构可以通过使用来简化类型开关 https://golang.org/ref/spec#Switch_statements像这样:

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 field).

它看起来是这样的:

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{}))

输出(尝试一下去游乐场 https://play.golang.org/p/tXEX5l_R677):

[] <nil>
[] <nil>
[] unknown image type main.unknownImage
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

断言接口的类型 的相关文章

  • 为什么我无法导入“内置”pkg?

    cat test go package main import builtin func main return go run test go can t find import builtin 我只是好奇 因为该文件存在并且已正确打包 但
  • 尝试创建问题时 GitHub API 422 出现意外错误响应

    当向 GitHub API V3 发布问题时 我收到了意外的响应 即422不可处理的实体 但是 错误的详细信息是针对搜索端点的 而不是针对 POST 创建端点的 message 验证失败 errors resource 搜索 field q
  • 如何将 interface{} 转换回其原始结构?

    我需要一种方法将结构 接口动态转换回其原始对象 我可以在里面添加方法 函数 基本上我需要这样的东西 MyStruct gt Interface gt MyStruct 在最终转换时 除了结构内部的内容之外 我对原始结构一无所知 所以我不能这
  • struct{} 和 struct{}{} 在 Go 中如何工作?

    我想知道 Go 中的 struct 和 struct 是什么意思 示例如下 array index struct or make map type struct struct is a keyword https golang org re
  • 重写 ResponseWriter 接口以捕获 HTTP 错误

    我正在用 Go 编写一个 Web 应用程序 虽然各种 mux 库提供了一种设置自定义 404 错误处理程序的方法 但没有任何其他 4xx 和 5xx 错误代码 一个建议是重写 ResponseWriter 接口中的 WriteHeader
  • 从 C 调用带有字符串参数的 Go 函数?

    我可以从 C 调用一个没有参数的 Go 函数 按照下面的 https github com joeprivacy crefgo hello world 这通过编译go build和打印 Hello from Golang main func
  • Go 中的格式错误 - %s %v 或 %w

    s v and w可用于格式化 Go 中的错误 将它们转换为字符串 fmt Errorf 它们在 Go 自己的工具中的使用方式似乎有所不同 In cmd go internal get path go https github com go
  • 为什么 golang 堆配置文件中的“Total MB”小于顶部的“RES”?

    我有一个用 go 编写的服务 在运行时需要 6 7G 内存 RES 在顶部 所以我使用 pprof 工具试图找出问题所在 go tool pprof pdf http
  • 如何更改“go build”的库路径

    我正在尝试与 goncurses 一起工作 在 Centos 6 上 ncurses 库很旧 5 7 想要 5 9 所以我从源代码构建了 ncurses 并将其安装到 usr lib usr include 等中 如何告诉 go get 针
  • 使用私有 git 存储库时的 go 工作区结构

    当你不使用 github 时 我一直在尝试找出 go 代码 工作区的标准文件夹布局 结构 我可以看到如何go get在获取 github 项目时有效 但假设我自己的 git 项目不会有 github com username project
  • go:找到模块但不包含包

    我正在尝试安装 go 的网络包 但收到 不包含包错误 终端截图 我咨询过 go 模块 latest 已找到但不包含包 https stackoverflow com questions 62974985 go module latest f
  • IntelliJ 2017.1.2 GOLANG 调试不适用于包中的断点

    我的应用程序由一个 main go 文件和一些包组成 当在 main go 中命中断点时 IntelliJ 按预期工作 显示变量值等 但是 当在不同的包中设置断点时 除了被命中之外 不会显示任何变量 并且不会跳过 进入功能按预期工作 被击中
  • Go中funcappend的实现在哪里?

    我对 go 非常感兴趣 并尝试阅读 go 函数的实现 我发现其中一些函数没有实现 如追加或调用 The append built in function appends elements to the end of a slice If i
  • 带 cookie 身份验证的 Gorilla websocket

    这是我的设置 我正在构建一个带有用户登录的服务 使用 Negroni 和 Gorilla 登录后 用户会获得一个会话 cookie 服务器使用该会话 cookie 来授权受保护的端点 受保护的端点之一允许用户 客户端与服务器打开 Webso
  • Cgo 生成的源无法在 MVC 上编译

    我有一个用 CGo 制作的共享库 它在 Linux 和 Android 上链接得很好 但是 当使用 Microsoft Visual Studio 2017 在 Windows 10 上进行编译时 出现以下错误 Microsoft R Pr
  • Golang 网络爬虫 NTLM 身份验证

    Golang 网络抓取工具需要从经过 NTLM 验证的网页中提取信息 有了有效的用户名和密码 网络抓取工具如何与服务器进行 NTLM 4 次握手 以获得对后面受保护网页的访问权限 url username password http www
  • Google Cloud Kubernetes 上任务队列的替代方案

    我发现任务队列主要用于App Engine标准环境 我正在将现有服务从 App Engine 迁移到 Kubernetes 任务队列的一个好的替代方案是什么 推送队列是当前正在使用的队列 我在线阅读文档并浏览了此链接 何时使用 PubSub
  • 无需时间即可生成随机字符串?

    我知道如何使用 Runes 和播种 rand Init 在 go 中生成随机字符串time UnixNano 我的问题是 是否可以 使用 stdlib 在不使用当前时间戳 安全 的情况下播种 rand 此外 我问 因为仅仅依靠时间来为敏感操
  • Golang标志:忽略丢失的标志并解析多个重复的标志

    我是 Golang 新手 一直无法使用 flag 找到这个问题的解决方案 如何使用 flag 以便我的程序可以处理此类调用 其中 term 标志可能出现可变次数 包括 0 次 myprogram f flag1 myprogram f fl
  • 如何使用 Java 原生接口从 Java 调用 Go 函数?

    可以通过以下方式调用 C 方法JNA https en wikipedia org wiki Java Native AccessJava 中的接口 如何使用 Go 实现相同的功能 package main import fmt impor

随机推荐

  • 如何以编程方式为 UINavigationController 子类化 UINavigationBar?

    我正在使用自定义的drawRect函数来绘制UINavigationBar在我的 iOS4 应用程序中 它不使用图像 仅使用 CoreGraphics 因为你不能在中实现drawRectUINavigationBariOS5 中的类别 Ap
  • JavaScript 唯一浏览器 ID

    有没有办法在javascript中为浏览器创建一个唯一的ID 我说的不是每次生成时都是随机的 ID 而是生成该 ID 的浏览器所特有的 ID 而且还考虑了运行该 ID 的计算机 Example Windows 7 Chrome 可能会生成
  • Ionic Zip 仅提取特定文件夹

    我有一个案例 我需要使用 C Ionic zip 库提取 Zip 文件 Zip 文件包含多个文件夹 我想提取特定文件夹并将其复制到特定目的地 例如名为 abc zip 的 Zip 文件和目录结构如下 父目录 gt 子目录1 gt 文件a 文
  • 从文档大纲(书签)中获取页码

    我正在使用 itext7 库来操作一些现有的 PDF 由于某种原因 我无法从大纲中获取页码 我想我应该以某种方式从Pdf目的地 http itextsupport com apidocs itext7 latest com itextpdf
  • 每天都会对 Java 8 Stream API 中的实体进行惰性排序吗?

    我有一个很大的 Java 8 Stream Stream
  • 字符串的哈希函数

    我正在用 C 语言研究哈希表 并且正在测试字符串的哈希函数 我尝试的第一个功能是添加 ascii 代码并使用模 100 但我的第一次数据测试结果很差 130 个单词有 40 次碰撞 最终输入数据将包含 8000 个单词 它是存储在文件中的字
  • 如何显示R中两个日期之间发生的事件

    我的问题看起来很简单 我希望如此 我有一个数据框 其中包含疾病诊断日期 指示患者服用哪种药物 或暴露和未暴露组 的二元变量 药物的开始和停止日期以及总体停止日期 ID Diag date Treatment End date Drug st
  • c3p0中的资源无法检出的原因是什么?

    因此 我正在研究 c3p0 API 来调试我们的一个生产问题 该问题导致在检查连接时出现堆栈溢出错误 我发现下面的评论BasicResourcePool班级的checkoutResource method This function rec
  • Vuetify 标准设置(babel/eslint)图像加载失败

    我正在开发一个 VueJS 项目 并尝试在轮播上加载图像 我正在使用标准设置并将图像放在资产文件夹中 我引用图像 URL
  • Storybook 需要导出默认的 Ant Design 组件才能应用样式

    我希望使用 Ant Design 设计一些 React 组件 并将它们记录在 Storybook 中 故事书和组件都编写正确且有效 模态故事 js import React from react import action from sto
  • python中具有相同名称的对象引用不同的id

    在下面的代码片段中 两个对象名为div在第 1 行和第 2 行创建 python如何区分两者div在同一作用域下创建的对象 When id 应用于两个对象 对于相似的命名对象会显示两个不同的地址 为什么会这样呢 def div a b re
  • webclient 方法对我的 Silverlight 应用程序不可用

    尝试用 C 进行基本的 Web 客户端数据拉取 这些方法在 Visualstudio 中不可用 并且代码无法编译 snip WebClient client new WebClient byte resp client DownloadDa
  • Pytorch:交叉熵损失中的权重

    我试图通过一个实际的例子来理解 CrossEntropyLoss 中的权重是如何工作的 所以我首先运行标准 PyTorch 代码 然后手动运行 但损失并不相同 from torch import nn import torch softma
  • Keras:网络不使用 fit_generator() 进行训练

    我在大型数据集上使用 Keras 使用 MagnaTagATune 数据集进行音乐自动标记 所以我尝试将 fit generator 函数与自定义数据生成器一起使用 但损失函数和指标的值在训练过程中不会改变 看起来我的网络根本没有训练 当我
  • 如何在 Ubuntu 上修复 Nokogiri?

    我在我的工作站上运行 Ubuntu 13 04 并使用 ruby 2 0 0 它是通过 RVM 安装的 aptitude 显示 libxml2 Package libxml2 State installed Automatically in
  • java扩展类有两种类型

    在java中我有以下内容 ClassA obj new ClassB where ClassB extends ClassA 是类型的对象ClassA or ClassB或两者 如果我们有 ClassB obj new ClassB 看来很
  • Grails3文件上传maxFileSize限制

    我正在尝试更新 Grails 3 中的文件上传 maxFileSize 限制 并尝试了以下配置src main resources application properties application groovy and applicat
  • Chisel 中的矩阵运算

    Chisel是否支持加法 乘法 转置等矩阵运算 如果没有 实施它们的最佳方法是什么 向量怎么样 Chisel 不支持矩阵运算 它是一种用于编写实现此类操作的硬件生成器的 DSL 有关专用数学硬件生成器的示例 请参阅 Hwacha 硬件矢量单
  • 列出用户在过去几天签入 TFS 的所有文件

    我们有很多项目 每个项目都有几个文件 可以从主解决方案根 项目级别和个人级别签入文件 有没有办法找到特定用户在过去几天签入的所有级别的所有文件 如果安装了 TFS 电动工具 则可以在 Visual Studio 命令提示符下使用命令 tfp
  • 断言接口的类型

    在一般情况下 我无法优雅地将图像的像素作为数组获取 f err os Open imgPath check err defer f Close img err image Decode bufio NewReader f check err