当前位置: 首页 > 后端技术 > Java

PHP两者都有,那么为什么Go不支持调用带命名参数的函数呢?

时间:2023-04-01 16:46:19 Java

大家好,我是炸鱼。之前在《Go 语言设计哲学》电子书中分享了《为什么 Go 不支持函数重载和缺省参数?》的想法和原因。最近,一位从其他编程语言转战Go的同学提出了以下灵魂拷问。《为什么Go不能像PHP和Python一样,在调用函数的时候直接传入参数名和值,这样就不用看这个的形参的名称,类型等了功能。显然PHP8支持它吗?今天想一想命名参数的特性,看看Go是怎么回事。命名参数如果有一个命名参数的函数,当我们调用一个函数/方法时,传入函数的参数不需要固定位置,可以随意调整位置,只要名字是正确的。一些工具甚至基于此做自动化文档等自描述场景。PHP8示例:functionhello(string$name,int$age){echo$name,$age;}//两次调用的参数位置不同hello(name:'friedfish',age:18);hello(age:18,name:'炸鱼');理想的Go示例:packagemainfuncsum(aint,bint)int{returna+b}funcmain(){resp:=sum(a=7,b=28)println(resp)}由于不支持,运行编译会报错:./prog.go:8:15:syntaxerror:unexpected=inargumentlist;可能缺少逗号或)Go必须是以下代码:funcsum(aint,bint)int{returna+b}funcmain(){resp:=sum(7,28)println(resp)//输出结果:35}即根据函数声明的参数位置传入,运行成功。设计哲学在讨论错误处理、函数重载、默认参数等社区问题时,Go语言总是采用它的设计哲学:“明确大于隐喻”,追求清晰、明确,或者说“少即是多”。每次我看到不符合这个概念的提案或讨论时,基本的Go团队都可以围绕这个论点给出一堆理由并拒绝它。这篇文章中提到的带命名参数的函数的传递看起来非常明确和清晰。似乎很符合Go的设计理念。我觉得应该没有吧?社区思考在golang-nuts邮件组多年的讨论中,有以下几类论点作为支持:这是一个语言设计和可读性问题,“命名参数”和“默认参数”基本成对出现在语言中设计时,需要考虑是否合适。还会有加号,相当于引入了很多新的语法特点,可以玩出戏来。这些特性的引入会给Go带来新的语法复杂性。如果更改函数参数名称,是否会破坏兼容性?调用者是否必须更改所有这些?如果有同名的参数名,谁在前?如何覆盖?如果太长,函数调用会不会太难以接受?组合结构重写方法时,方法参数名是否需要保持一致?一系列新问题随之而来。引入之后会产生大量的函数可选参数(命名参数+默认参数)。本来只需要知道函数的参数是什么,但是引入之后需要查看名称、默认值、对应的默认逻辑等,会增加Programmer的心理负担。编译器本身不需要关注这些信息。无需为此特性增加编译器的各种开销。编译器没有理由在编译后的代码中存储函数的参数名(需要注意含义)。我们在讨论中也提到了这个特性可以使用go:generate的特性来实现类似的功能。有兴趣的朋友可以看看开源库go-named-params。显然,官方的态度是加入命名参数特性弊大于利,贸然增加会影响Go本身标榜的优势(简洁)。我觉得没必要加,工具的问题需要工具自己解决。小结在本文中,我们分析和解释了其他编程语言现有的“命名参数”特性。显然,在讨论过程中,Go团队认为这个特性似乎对静态语言的好处太少,尤其是对Go团队。添加它会影响它自己的风格(少即是多),也可能会影响性能。实在是没有必要。语言之间功能特性的比较是一个由来已久的难题。如果它们都一样,那岂不是一个庞大的单体编程语言?这显然是不现实的。文章持续更新中。可以微信搜索【脑补炸鱼】阅读。本文已收录在GitHubgithub.com/eddycjy/blog中。学习Go语言可以看Go学习地图和路线。欢迎星星提醒。Go书系列Go语言入门系列:初探Go项目实战Go语言编程之旅:深入使用Go做项目Go语言设计哲学:理解Go的Why与设计思维Go语言进阶之旅:走得更远Go源码推荐阅读醒醒吧,以后就没有Go2了!Go1.20的那些事:PGO、编译速度、错误处理等新特性,你知道多少?向斯威夫特学习?Go考虑简单的字符串插值特性