注意细节

在之前的文章中,我提到了一个关于 *accept interfaces, return structs* 的参考指南,在查看同事代码的时候经常会被问“为什么”。特别是这不是一个必须遵守的规则。这个想法的关键点以及理解什么时候妥协,在于维护项目灵活性和避免抢占抽象(译者注:“Preemptive abstractions” 并发系统中连续组件的轻量级验证方案的一种抽象技术)之间的平衡。

抢占抽象让系统变得复杂

除了因为太多的迂回方式所造成的问题之外,所有的计算机科学问题都能够通过另一个级别的迂回方式来解决。

  • David J. Wheeler

软件工程师喜欢抽象。个人看法,我从未看到过一个同事参与写代码超过他为了某个事务建立抽象多。Go 语言从结构中抽象出接口,这种处理方式会产生嵌入复杂性。遵循你并不需要它软件设计理念,如果不需要就没有理由增加复杂性。一个常见的返回接口的理由是让用户把注意力放在函数所提供的 API 上。在 Go 中因为隐含实现了接口,所以这并不需要。返回结构的公共函数就成为那个API

永远只有当你真正需要的时候才抽象,不要因为预见可能会需要而抽象

一些语言需要你预见每一个可能从未用过的接口。隐含实现接口一个最大的好处,就是允许你在后面实际需要的时候优雅的抽象事务,而不是需要你预先抽象出来。

使用者眼中的需求 当你真正需要他们的时候

你怎么知道什么时候需要抽象?对于返回类型来说,比较容易。你是写函数的人,所以你确切的知道什么时候需要抽象返回值。

对于输入参数来说,是否需要不在你的控制范围之内。你也许认为你的数据模型足够了,但是一个用户可能需要和某些属性封装一下。如果可能的话,可以预想一下每个调用你的函数的情况,但这是比较困难的。这种可以控制输出,但是不能预期用户输入的不平衡的状况产生了一种强烈的偏见,抽象输入而不是输出。

去掉无用的代码细节

复杂的做鸡蛋的方法 ,简化的另一个方面是去除不需要的细节。类似菜单函数:给一个输入然后你得到一个蛋糕!不需要列出做蛋糕的材料。同样的,函数也不需要列出不使用的输入参数。下面的函数你会怎么想?

func addNumbers(a int, b int, s string) int {return a + b
}

对于大多数程序员来说很明显参数 s 是不需要的。当参数是结构的时候就不那么明显了。

type Database struct{ }
func (d *Database) AddUser(s string) {...}
func (d *Database) RemoveUser(s string) {...}
func NewUser(d *Database, firstName string, lastName string) {d.AddUser(firstName + lastName)
}

就像一个写满了配料的菜单一样,NewUser 输入参数是一个有很多功能的 Database 对象。实际上只需要 AddUser 但是却得到了额外的 RemoveUser。接口允许我们在创建函数的时候只依赖我们需要的功能。

type DatabaseWriter interface {AddUser(string)
}
func NewUser(d DatabaseWriter, firstName string, lastName string) {d.AddUser(firstName + lastName)
}

Dave Cheney在写接口隔离原则的时候也提到了这一点。他还描述了一些关于限制输入的其他好处,值得读一下。概括一下就是:Dave Cheney 在写接口隔离原则的时候也提到了这一点。他还描述了一些关于限制输入的其他好处,值得读一下。概括一下就是:

依照需求描述的结果也就是函数-仅仅是需要可写并且提供相应的功能 我会按照这个思想,重新考虑上面的函数 addNumbers,很明显不需要参数 s 字符串,函数 NewUser 同样也不需要一个包括 RemoveUserDatabase参数。

总结理由和审查例外情况

主要的理由如下:

  • 移除不需要的抽象
  • 在函数参数上用户需求的歧义
  • 简化函数参数 这些理由也允许有例外的情况。例如,如果你的函数实际上返回多种类型而不是一个接口。同样地,如果函数是私有的,你能控制输入参数,会偏向于不要做抢占抽象。对于第三条规则,go 没有方式可以抽象出结构成员的值。 所以,如果你的函数需要访问结构成员(并且不只是结构方法),那么你必须接受结构作为参数。

问答

提问:如果 Database 有很多方法,比如 20 个,那么如何处理呢? 回答:一个结构可能有 20 个方法,但是一个方法不需要调用那么多方法。 试着把这些方法按组分类,比如读的方法,写的方法,管理的方法等等。这样需要 Database 的函数可以使用方法子集来处理。

首发于:https://studygolang.com/articles/12397

struct interface_今天就谈谈go中的接受 interface 参数,返回 struct相关推荐

  1. struct interface_GCTT | 接受 interface 参数,返回 struct 在 go 中意味着什么

    注意细节 在之前的文章中,我提到了一个关于 accept interfaces, return structs 的参考指南,在查看同事代码的时候经常会被问"为什么".特别是这不是一 ...

  2. python中函数的可变参数_简单谈谈Python中函数的可变参数

    前言 在Python中定义函数,可以用必选参数.默认参数.可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,但是请注意,参数定义的顺序必须是:必选参数.默认参数.可变参数和关键字参数. ...

  3. this调用语句必须是构造函数中的第一个可执行语句_谈谈JavaScript中的函数构造式和new关键字...

    您是否曾困惑于 Javascript 中的new关键字呢?是否曾想理解关于 function 和 constructor 的区别是什么呢? 大多数 Javascript 的新开发者不太想要使用new关 ...

  4. html js脚本限制 正则,简单谈谈JS中的正则表达式

    1.正则表达式包括两部分 ①定义正则表达式的规则: ②正则表达式的模式(i/g/m): 2.声明正则表达式 ① 字面量声明: var reg = /表达式规则/表达式模式: eg:var reg = ...

  5. Linux存储保护,谈谈Linux中的存储保护

    谈谈Linux中的存储保护 以下讨论的内容是以i386平台为基础的 Linux将4G的地址划分为用户空间和内核空间两部分.在Linux内核的低版本中(2.0.X),通常0-3G为用户空间,3G-4G为 ...

  6. 谈谈JAVA中的安全发布

    谈谈JAVA中的安全发布 昨天看到一篇文章阐述技术类资料的"等级",看完之后很有共鸣.再加上最近在工作中越发觉得线程安全性的重要性和难以捉摸,又掏出了<Java并发编程实战& ...

  7. Spark精华问答 | 谈谈spark中的宽窄依赖

    总的来说,Spark采用更先进的架构,使得灵活性.易用性.性能等方面都比Hadoop更有优势,有取代Hadoop的趋势,但其稳定性有待进一步提高.我总结,具体表现在如下几个方面. 1 Q:Spark ...

  8. 谈谈C#中的三个关键词new , virtual , override

    谈谈C#中的三个关键词new , virtual , override C#支持单继承,说到继承就不得不说new,virtual和override这三个关键词,灵活正确的使用这三个关键词,可以使程序结 ...

  9. 谈谈java中成员变量与成员方法继承的问题

    谈谈java中成员变量与成员方法继承的问题 关于成员变量和成员方法的的继承问题,我也可以做一个小测试,来看看结果. 首先我们先创建一个父类: 其次再创建一个子类,子类中要比父类中少一个成员方法: 这样 ...

最新文章

  1. Shiro总是将我重定向到login.jsp
  2. 【struts2+hibernate+spring项目实战】java监听器实现权限控制系统和资源获取优化(ssh)
  3. 设置qt的QChart曲线背景色透明
  4. 猎取人心的36条黄金法则
  5. SphereEx 完成近千万美元 Pre-A 轮融资,连接企业数据与应用,构建新一代数据库生态引擎
  6. syslinux 制作多系统启动U盘
  7. C#将LINQ数据集转换为Datatable
  8. 携程集团CMO孙波入选“2021亚太营销领袖50强”榜单
  9. wpf之界面控件MaterialDesignInXAML
  10. MOOSE相场模块的内核模型
  11. linux qt 触摸屏事件,利用触摸屏获取事件坐标
  12. 单机配置tomcat 8 集群
  13. Centos6 安装可视化界面
  14. poedit使用(本地化和国际化)
  15. android 钉钉考勤日历,vue实现钉钉的考勤日历
  16. 算法高级(42)-大数定律-澳门皇家菠菜,为什么你逢赌必输?
  17. kubernetes进阶之路(十六)~~~Storage系列之StorageClass
  18. win7局域网自建ftp服务器,win7系统搭建FTp服务器局域网内传输文件的解决教程
  19. 邮箱 万维网通讯 smtp
  20. 人工智能研究的内容:_更深入:人工智能研究的思想史

热门文章

  1. vue 监听对象里的特定数据
  2. PostgreSQL 10 自定义并行计算聚合函数的原理与实践
  3. Class yii\base\Exception
  4. 【c++】构造函数初始化列表中成员初始化的次序性
  5. Alpha冲刺(2/10)——2019.4.24
  6. 查询两个表合并成一个表
  7. SpriteKit游戏开发适配iPad/iPhone6/7/8/Plus及iPhoneX的尺寸及安全区域
  8. 利用HttpWebRequest和HttpWebResponse做黑客注射工具
  9. 使用组合改进软件测试用例的生成2
  10. shell脚本eval