Go是一门面向对象编程语言吗

Go语言已经开源13年了[1],在近期TIOBE[2]发布的2023年3月份的编程语言排行榜中,Go再次冲入前十,相较于Go在2022年底的排名[3]提升了2个位次:

974672559ca6b5a409f694d550e2420c.png

《Go语言第一课》专栏[4]中关于Go在这两年开始飞起的“预言”也正在逐步成为现实^_^,大家学习Go的热情也在快速提升, 《Go语言第一课》专栏[5]的学习的人数年后也快速增加,快突破2w了。

很多专栏的订阅者都是第一次接触Go,他们中的很多是来自像Java, Ruby这样的OO(面向对象)语言阵营的,他们学习Go之后的第一个问题便是:Go是一门OO语言吗?在这篇博文中,我们就来探讨一下。

一. 溯源

在公认的Go语言“圣经”《Go程序设计语言》[6]一书中,有这样一幅Go语言与其主要的先祖编程语言的亲缘关系图:

1bac6b4b1c713ec4ebb83245686261ad.png

从图中我们可以清晰看到Go语言的“继承脉络”:

  • 从C语言[7]那里借鉴了表达式语法、控制语句、基本数据类型、值参数传递、指针等;

  • 从Oberon-2语言[8]那里借鉴了package、包导入和声明的语法,而Object Oberon提供了方法声明的语法。

  • 从Alef语言[9]以及Newsqueak语言[10]中借鉴了基于CSP[11]的并发语法。

我们看到,从Go先祖溯源的情况来看,Go并没有从纯面向对象语言比如Simula、SmallTalk[12]等那里取经。

Go诞生于2007年,开源于2009年,那正是面向对象语言和OO范式大行其道的时期。不过Go设计者们觉得经典OO的继承体系对程序设计与扩展似乎并无太多好处,还带来了较多的限制,因此在正式版本中并没有支持经典意义上的OO语法,即基于类和对象实现的封装、继承和多态这三大OO主流特性。

但这是否说明Go不是一门OO语言呢?也不是!带有面向对象机制的Object Oberon[13]也是Go的先祖语言之一,虽然Object Oberon的OO语法又与我们今天常见的语法有较大差异。

就此问题,我还特意咨询了ChatGPT[14]^_^,得到的答复如下:

59a5f53a58971da0724360e41313e28c.png

ChatGPT认为:Go支持面向对象,提供了对面向对象范式基本概念的支持,但支持的手段却并不是类与对象。

那么针对这个问题Go官方是否有回应呢?有的,我们来看一下。

二. 官方声音

Go官方在FAQ中就Go是否是OO语言做了简略回应[15]

Is Go an object-oriented language?Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is easy to use and in some ways more general. There are also ways to embed types in other types to provide something analogous—but not identical—to subclassing. Moreover, methods in Go are more general than in C++ or Java: they can be defined for any sort of data, even built-in types such as plain, “unboxed” integers. They are not restricted to structs (classes).Also, the lack of a type hierarchy makes “objects” in Go feel much more lightweight than in languages such as C++ or Java.

粗略翻译过来就是:

Go是一种面向对象的语言吗?是,也不是。虽然Go有类型和方法,并且允许面向对象的编程风格,但却没有类型层次。Go中的“接口”概念提供了一种不同的OO实现方案,我们认为这种方案更易于使用,而且在某些方面更加通用。还有一些可以将类型嵌入到其他类型中以提供类似子类但又不等同于子类的机制。此外,Go中的方法比C++或Java中的方法更通用:Go可以为任何数据类型定义方法,甚至是内置类型,如普通的、“未装箱的”整数。Go的方法并不局限于结构体(类)。此外,由于去掉了类型层次,Go中的“对象”比C++或Java等语言更轻巧。

“是,也不是”!我们看到Go官方给出了一个“对两方都无害”的中庸的回答。那么Go社区是怎么认为的呢?我们来看看Go社区的一些典型代表的观点。

三. 社区声音

Jaana Dogan[16]和Steve Francia[17]都是前Go核心团队成员,他们在加入Go团队之前对“Go是否是OO语言”这一问题也都有自己的观点论述。

Jaana Dogan在《The Go type system for newcomers》[18]一文中给出的观点是:Go is considered as an object-oriented language even though it lacks type hierarchy,即“Go被认为是一种面向对象的语言,即使它缺少类型层次结构”。

而更早一些的是Steve Francia在2014年发表的文章《Is Go an Object Oriented language?》[19]中的结论观点:Go,没有对象或继承的面向对象编程,也可称为“无对象”的OO编程模型。

两者表达的遣词不同,但含义却异曲同工,即Go支持面向对象编程,但却不是通过提供经典的类、对象以及类型层次来实现的

那么Go究竟是以何种方式实现对OOP的支持的呢?我们继续看!

四. Go的“无对象”OO编程

经典OO的三大特性是封装、继承与多态,这里我们看看Go中是如何对应的。

1. 封装

封装就是把数据以及操作数据的方法“打包”到一个抽象数据类型中,这个类型封装隐藏了实现的细节,所有数据仅能通过导出的方法来访问和操作。这个抽象数据类型的实例被称为对象。经典OO语言,如Java、C++等都是通过类(class)来表达封装的概念,通过类的实例来映射对象的。熟悉Java的童鞋一定记得《Java编程思想》[20]一书的第二章的标题:“一切都是对象”。在Java中所有属性、方法都定义在一个个的class中。

Go语言没有class,那么封装的概念又是如何体现的呢?来自OO语言的初学者进入Go世界后,都喜欢“对号入座”,即Go中什么语法元素与class最接近!于是他们找到了struct类型。

Go中的struct类型中提供了对真实世界聚合抽象的能力,struct的定义中可以包含一组字段(field),如果从OO角度来看,你也可以将这些字段视为属性,同时,我们也可以为struct类型定义方法(method),下面例子中我们定义了一个名为Point的struct类型,它拥有一个导出方法Length:

type Point struct {x, y float64
}func (p Point) Length() float64 {return math.Sqrt(p.x * p.x + p.y * p.y)
}

我们看到,从语法形式上来看,与经典OO声明类的方法不同,Go方法声明并不需要放在声明struct类型的大括号中。Length方法与Point类型建立联系的纽带是一个被称为receiver参数的语法元素。

那么,struct是否就是对应经典OO中的类呢? 是,也不是!从数据聚合抽象来看,似乎是这样, struct类型可以拥有多个异构类型的、代表不同抽象能力的字段(比如整数类型int可以用来抽象一个真实世界物体的长度,string类型字段可以用来抽象真实世界物体的名字等)。

但从拥有方法的角度,不仅是struct类型,Go中除了内置类型的所有其他具名类型都可以拥有自己的方法,哪怕是一个底层类型为int的新类型MyInt:

type MyInt intfunc(a MyInt)Add(b int) MyInt {return a + MyInt(b)
}

2. 继承

就像前面说的,Go设计者在Go诞生伊始就重新评估了对经典OO的语法概念的支持,最终放弃了对诸如类、对象以及类继承层次体系的支持。也就是说:在Go中体现封装概念的类型之间都是“路人”,没有亲爹和儿子的关系的“牵绊”

谈到OO中的继承,大家更多想到的是子类继承了父类的属性与方法实现。Go虽然没有像Java extends关键字那样的显式继承语法,但Go也另辟蹊径地对“继承”提供了支持。这种支持方式就是类型嵌入(type embedding),看一个例子:

type P struct {A intb string
}func (P) M1() {
}func (P) M2() {
}type Q struct {c [5]intD float64
}func (Q) M3() {
}func (Q) M4() {
}type T struct {PQE int
}func main() {var t Tt.M1()t.M2()t.M3()t.M4()println(t.A, t.D, t.E)
}

我们看到类型T通过嵌入P、Q两个类型,“继承”了P、Q的导出方法(M1~M4)和导出字段(A、D)。

关于类型嵌入的具体语法说明,大家可以温习一下《十分钟入门Go语言》[21]

不过实际Go中的这种“继承”机制并非经典OO中的继承,其外围类型(T)与嵌入的类型(P、Q)之间没有任何“亲缘”关系。P、Q的导出字段和导出方法只是被提升为T的字段和方法罢了,其本质是一种组合,是组合中的代理(delegate)模式的一种实现。T只是一个代理(delegate),对外它提供了它可以代理的所有方法,如例子中的M1~M4方法。当外界发起对T的M1方法的调用后,T将该调用委派给它内部的P实例来实际执行M1方法。

以经典OO理论话术去理解就是T与P、Q的关系不是is-a,而是has-a的关系

3. 多态

经典OO中的多态是尤指运行时多态,指的是调用方法时,会根据调用方法的实际对象的类型来调用不同类型的方法实现。

下面是一个C++中典型多态的例子:

#include <iostream>class P {public:virtual void M() = 0;
};class C1: public P {public:void M();
};void C1::M() {std::cout << "c1.M()\n";
}class C2: public P {public:void M();
};void C2::M() {std::cout << "c2.M()\n";
}int main() {C1 c1;C2 c2;P *p = &c1;p->M(); // c1.M()p = &c2;p->M(); // c2.M()
}

这段代码比较清晰,一个父类P和两个子类C1和C2。父类P有一个虚拟成员函数M,两个子类C1和C2分别重写了M成员函数。在main中,我们声明父类P的指针,然后将C1和C2的对象实例分别赋值给p并调用M成员函数,从结果来看,在运行时p实际调用的函数会根据其指向的对象实例的实际类型而分别调用C1和C2的M。

显然,经典OO的多态实现依托的是类型的层次关系。那么对应没有了类型层次体系的Go来说,它又是如何实现多态的呢?Go使用接口来解锁多态

和经典OO语言相比,Go更强调行为聚合与一致性,而非数据。因此Go提供了对类似duck typing的支持,即基于行为集合的类型适配,但相较于ruby等动态语言,Go的静态类型机制还可以保证应用duck typing时的类型安全。

Go的接口类型本质就是一组方法集合(行为集合),一个类型如果实现了某个接口类型中的所有方法,那么就可以作为动态类型赋值给接口类型。通过该接口类型变量的调用某一方法,实际调用的就是其动态类型的方法实现。看下面例子:

type MyInterface interface {M1()M2()M3()
}type P struct {
}func (P) M1() {}
func (P) M2() {}
func (P) M3() {}type Q int 
func (Q) M1() {}
func (Q) M2() {}
func (Q) M3() {}func main() {var p Pvar q Qvar i MyInterface = pi.M1() // P.M1i.M2() // P.M2i.M3() // P.M3i = qi.M1() // Q.M1i.M2() // Q.M2i.M3() // Q.M3
}

Go这种无需类型继承层次体系、低耦合方式的多态实现,是不是用起来更轻量、更容易些呢!

五. Gopher的“OO思维”

到这里,来自经典OO语言阵营的小伙伴们是不是已经找到了当初在入门Go语言时“感觉到别扭”的原因了呢!这种“别扭”就在于Go对于OO支持的方式与经典OO语言的差别:秉持着经典OO思维的小伙伴一上来就要建立的继承层次体系,但Go没有,也不需要。

要转变为正宗的Gopher的OO思维其实也不难,那就是“prefer接口,prefer组合,将习惯了的is-a思维改为has-a思维”。

六. 小结

是时候给出一些结论性的观点了:

  • Go支持OO,只是用的不是经典OO的语法和带层次的类型体系;

  • Go支持OO,只是用起来需要换种思维;

  • 在Go中玩转OO的思维方式是:“优先接口、优先组合”。


“Gopher部落”知识星球[22]旨在打造一个精品Go学习和进阶社群!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!2023年,Gopher部落将进一步聚焦于如何编写雅、地道、可读、可测试的Go代码,关注代码质量并深入理解Go核心技术,并继续加强与星友的互动。欢迎大家加入!

de467b6a370cc3631a0e4c82d79ce573.png

f4f99ddfc25995c762fa0bd3954e4282.png

0830aa31e73636c7d1a1609677ce4169.png

Gopher Daily(Gopher每日新闻)归档仓库 - https://github.com/bigwhite/gopherdaily

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx

  • 微博2:https://weibo.com/u/6484441286

  • 博客:tonybai.com

  • github: https://github.com/bigwhite

14a955e88673ae63c401614c800991b9.png

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

参考资料

[1] 

Go语言已经开源13年了: https://tonybai.com/2022/11/11/go-opensource-13-years/

[2] 

TIOBE: https://www.tiobe.com/tiobe-index/

[3] 

2022年底的排名: https://tonybai.com/2022/12/29/the-2022-review-of-go-programming-language

[4] 

《Go语言第一课》专栏: http://gk.link/a/10AVZ

[5] 

《Go语言第一课》专栏: http://gk.link/a/10AVZ

[6] 

《Go程序设计语言》: http://www.gopl.io

[7] 

C语言: https://tonybai.com/tag/c

[8] 

Oberon-2语言: https://cseweb.ucsd.edu/~wgg/CSE131B/oberon2.htm

[9] 

Alef语言: http://doc.cat-v.org/plan_9/2nd_edition/papers/alef/ref

[10] 

Newsqueak语言: https://newspeaklanguage.org

[11] 

CSP: https://cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/csp.html

[12] 

SmallTalk: http://en.wikipedia.org/wiki/Smalltalk

[13] 

Object Oberon: http://www.projectoberon.net/

[14] 

ChatGPT: https://chat.openai.com/chat

[15] 

Go官方在FAQ中就Go是否是OO语言做了简略回应: https://go.dev/doc/faq#Is_Go_an_object-oriented_language

[16] 

Jaana Dogan: https://rakyll.org/

[17] 

Steve Francia: https://spf13.com/

[18] 

《The Go type system for newcomers》: https://rakyll.org/typesystem/

[19] 

《Is Go an Object Oriented language?》: https://spf13.com/p/is-go-an-object-oriented-language/

[20] 

《Java编程思想》: https://book.douban.com/subject/2130190/

[21] 

《十分钟入门Go语言》: https://mp.weixin.qq.com/s/nRkEe5v3GNTjxJNbYflRag

[22] 

“Gopher部落”知识星球: https://wx.zsxq.com/dweb2/index/group/51284458844544

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14635.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何写出高质量的文章:从战略到战术

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

原力计划来了【协作共赢 成就未来】

catalogue &#x1f31f; 写在前面&#x1f31f; 新星计划持续上新&#x1f31f; 原力计划方向&#x1f31f; 原力计划拥抱优质&#x1f31f; AIGC&#x1f31f; 参加新星计划还是原力计划&#x1f31f; 创作成就未来&#x1f31f; 写在最后 &#x1f31f; 写在前面 哈喽&…

博弈论——选举/投票(voting)

文章目录 前言一、相对多数投票法&#xff08;Plurality Voting&#xff09;二、孔多塞准则&#xff08;The Condorcet Criterion&#xff09;三&#xff0c; 谷轮法&#xff08;Copeland method四&#xff0c;波达计数法&#xff08;Borda Count&#xff09;五&#xff0c;选举…

Java 设计模式(java design patterns)

什么是设计模式&#xff1f; 前辈们&#xff0c;在长期开发中为了解决某种重复出现的问题&#xff0c;经过长期的总结&#xff0c;代码结构优化&#xff0c;最终确定一套解决办法。 为什么学习设计模式&#xff1f; 对程序设是有帮助的&#xff0c;提高代码额可重用性&#…

叫ChatGPT用html+css+js写一个圣诞节代码,看看什么样子?

最近ChatGPT这么火&#xff0c;那就让他给我写点代码吧。 如何注册一个账号&#xff0c;参考&#xff1a;注册ChatGPT详细指南 注册不了的小伙伴们&#xff0c;咱们评论区见&#xff0c;问一个最想问的问题&#xff0c;看到就给你回复&#xff01; 我已经注册好了&#xff0c;…

前端实现六一儿童节祝福语分享,烟花特效助您表心意

部分数据来源&#xff1a;ChatGPT <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>六一儿童节祝福</title><style>body {background-image: url(https://picsum.photos/1920/1080);backgr…

chatgpt赋能python:10个好玩的Python代码-让编程更有趣!

10个好玩的Python代码- 让编程更有趣&#xff01; 作为一名有10年Python编程经验的工程师&#xff0c;我深刻理解到编程可以是一件令人兴奋和有趣的事情。Python是流行且多才多艺的编程语言&#xff0c;具有简洁易懂的语法和丰富的库&#xff0c;可以帮助开发人员快速轻松地实…

大型语言模型与文本摘要

大型语言模型与文本摘要 基于大型语言模型的抽取式摘要基于大型语言模型的零样本跨语言摘要基于大型语言模型的问答式摘要通过摘要任务评估大型语言模型的事实一致性基于大型语言模型的摘要事实一致性评估器未来方向大型语言模型的自我偏好基于大型语言模型生成提示基于大型语言…

ChatGPT玩起来真是上头,AI广泛应用元年体验AI之美

概述 ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型&#xff0c;一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xf…

推荐一款idea神级代码插件【Bito-ChatGPT】而且免费!- 第9篇

历史文章&#xff08;文章累计460&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 文…

ChatGPT - 获取简短的书籍摘要的Prompt

文章目录 Prompt例子 Prompt “总结[书籍名称]&#xff0c;并给我列出最重要的学习和观点。”例子

小米AX6000开启SSH后的高级用法

买的是RA72版本的AX6000,售价599,高通的CPU。 看看高颜值和唬人的外观,图示如下: 关于AX6000开启SSH的方法有很多介绍的,这里关键讲几点: 先升级RA72对应的固件,降级到41版本。 附上:miwifi_ra72_firmware_59812_1.0.41.bin 版本固件地址: http://cdn.cnbj1.fds.a…

为什么我觉得这次的chatGPT是真的智能AI

写在前面 openAI在2022年11月推出了chatGPT&#xff08;全称Chat Generative Pre-trained Transformer【聊天生成型預訓練變換模型】维基百科&#xff09;说的直白一点就是一个目前为止&#xff0c;这个星球上可以见到的最智能的机器人&#xff0c;他可以完成一些人类认知范围内…

第四届中国计算机教育大会“人工智能与大模型论坛”将于4月22日厦门召开

2023 年 ChatGPT 全球爆红&#xff0c;瞬间在国内引起了对大语言模型的热议。全球头部科技大厂再次站上了同一个赛道&#xff0c;很多 AI 领域的创业者、创投机构行动了起来&#xff0c;开启了大语言模型“军备竞赛”。人工智能与大模型技术的发展&#xff0c;离不开高校与产业…

chatgpt赋能python:Python培训:成为一名高薪Python工程师

Python培训&#xff1a;成为一名高薪Python工程师 Python已成为当今最流行的编程语言之一&#xff0c;它广泛应用于人工智能、机器学习、数据科学和Web开发等各个领域。许多公司都在寻找经验丰富的Python工程师来开发他们的产品。如果你想成为一名高薪Python工程师&#xff0c…

记一次和ChatGPT一起排查线上问题

某日现场技术支持找到了我&#xff0c;问我有个数据上报的功能&#xff0c;记录的都是上报失败&#xff0c;让我排查一下。我第一印象当然是甩锅&#xff0c;啊不对问一下情况&#xff0c;准备排查问题。 先交代一下基础情况&#xff1a;功能就是我们将我们系统的数据上报到对方…

AI 2.0时代,再看消费物联网十年

本文是「光锥智能」的「十年系列」之二&#xff0c;对前沿科技影响千行百业数字化和智能化的复盘和展望&#xff0c;第一篇《中国芯片投资十年》获得了业界科技、财经、创投和芯片垂类媒体的广泛关注。 【划重点】 从消费互联网、移动互联网到万物智联&#xff0c;正是一个“…

月薪13K!国企小哥抛弃“铁饭碗”转行测试,亲身经历告诉你选高薪or稳定

对于很多程序员来说&#xff0c;国企or大厂一直都是一个两难的抉择&#xff0c;该选择稳定还是高薪&#xff0c;许多小伙伴都在这个问题犯了难。 可他却用自己的努力和实际行动做出了最好的选择&#xff0c;为自己的职业道路画上了浓墨重彩的一笔。 话不多说&#xff0c;一起…

36张图,一次性补全网络基础知识

点击上方 前端Q&#xff0c;关注公众号 回复加群&#xff0c;加入前端Q技术交流群 转自&#xff1a;网络工程师笔记 OSI和TCP/IP是很基础但又非常重要的知识&#xff0c;很多知识点都是以它们为基础去串联的&#xff0c;作为底层&#xff0c;掌握得越透彻&#xff0c;理解上层时…

基于LLM的生成式AI正在快速变革RPA人机交互

如果问RPA对程序开发以及自动化有哪些贡献&#xff0c;其中一个答案便是它改变了人机交互&#xff08;HCI&#xff0c;human-computer interaction&#xff09;。 在传统工作流自动化工具中&#xff0c;软件开发人员不得不生成一个操作列表&#xff0c;使用内部应用程序编程接…