代码之家  ›  专栏  ›  技术社区  ›  Arnold Schrijver

Go中空接口的最佳实践?

  •  1
  • Arnold Schrijver  · 技术社区  · 5 年前

    我正在学习空界面。我发现,虽然关于Stackoverflow空界面的含义及其工作原理也有很多解释,但关于何时/为什么使用它们、何时避免、考虑因素是什么以及选择使用它们的利弊的最佳实践信息很少。

    在Go聊天室中,我读到了一些关于尽可能避免使用空界面的讨论,但没有适当的参数。其他人自豪地回应说,他们的代码设计中没有空接口。

    我最感兴趣的是用于库和框架(旨在供他人重用/扩展)。

    现在我正在阅读一个包含相关库的框架代码库,其中许多地方都有emtpy接口。其中一些让我感到困惑,我想知道是否所有的用法都是合理的。该框架提供了“用户管理”等功能 AppConfiguration 和 UserPreferences 是空接口。在代码的后面(在db层附近),用户的电子邮件在技术上被视为用户偏好。在接口定义中更具体不是更好吗?

    0 回复  |  直到 5 年前
        1
  •  3
  •   Arnold Schrijver    5 年前

    在Go聊天室中,我读到了一些关于尽可能避免使用空界面的讨论,但没有适当的参数。其他人自豪地回应说,他们的代码设计中没有空接口。

    最大的问题是你失去了所有的打字;例如,假设我有一个函数,我想对各种类型的数字进行操作,所以我写:

    func AddOne(n interface{}) int64 {
        switch nn := n.(type) {
            case int:
                return nn + 1
            case int8:
                return nn + 1
            // ... etc...
        }
    }
    

    但是,如果我将0.42(float64)传递给这个函数,或者字符串 "asd" ? 如果函数接受int64( func AddOne(n int64) int64 )然后我们就会收到警告 编译时 ,但与 interface{} 你什么也得不到,因为一切都是有效的。

    你能做的最好的事情就是在运行时处理这个问题,要么panic(),要么返回错误;这显然比编译时错误要模糊得多。

    这是迄今为止最大的不利因素。


    我得看看那些的细节 AppConfiguration 和 UserPreferences 特别是函数,但使用空接口有一些很好的理由;例如,当你想接受一些自定义结构,然后使用反射根据一些外部数据在结构上设置值时。这基本上就是这样的包 encoding/json 确实如此,但它也常用于解析某些配置文件等。

    听起来像 AppConfiguration 和 用户首选项 可能适合这个,因为库/框架不知道你的应用程序配置需要什么设置,也不知道有什么用户偏好。但就像我说的,没有细节很难确定。

    另一个用例是当你真的想接受各种各样的类型时;将参数传递给SQL查询是一个常见的例子,或者 fmt.Printf() .


    一般来说,避免 接口{} 可能是最好的,但如果你发现自己为了这样做而弯腰驼背,那么最好还是使用 接口{} 生活在缺乏打字的环境中。

        2
  •  1
  •   Alexander Trakhimenok    5 年前

    空命名接口在Go中没有意义,因为与C#等其他语言不同,任何类型(C#中的类)如果与接口签名匹配,都可以转换为特定接口。因此,在Go中,“类”(结构类型)不需要从接口继承(例如,在类型定义时声明接口)。

    那么,你的问题的答案是:

    Go中空接口的最佳实践是不要在Go中定义命名的空接口。

    更新 :由于下面的评论,我改变了主意,我同意为了文档和IDE中更快的导航,使用空命名接口的用例可能有限。