当前位置: 首页 > 科技观察

经验谈:学习Go语言的利弊

时间:2023-03-19 01:52:12 科技观察

在这个竞争日益激烈的社会,掌握一门新的语言或技能,意味着你比别人多了一个机会。但是万事开头难,学习新事物也是如此。如果开发人员想学习一门新的编程语言,他们应该选择什么?Go非常容易学习。当我刚开始学习Go时,我正在做一个个人项目,我必须掌握新的语法(我在学习一门新的编程语言时总是想出一个项目)。我决定创建一个命令行应用程序来枚举子域,以帮助查找资产中存在的漏洞赏金计划。为实现此功能,与gobuster类似,应用程序必须并行发出多个HTTP请求,但我想通过添加功能(例如抓取HTML响应以获取有趣的安全相关信息)来重构特定循环。我试图用go-routine解决这个问题,其中一个具有挑战性的部分是程序发出了未知数量的HTTP请求,因此它需要学习如何有效地处理这些请求。第一印象很快,我发现语法非常熟悉,即使我以前从未阅读过文档。这些概念对我来说似乎很直观(其他人可能不同意)。Defer的使用很简单。用于格式化字符串的fmt包似乎解决了一个我以前没有见过的问题。我开始意识到为什么Go作为一种新的编程语言在最近几年发展迅速。所以我决定稍微深挖一下Go语言的初衷,看看它是否值得花时间去学习。为什么开发Go语言Go语言是由Google开发的,目的是让多进程开发更高效、更安全,提高服务器长期运行的可维护性、可靠性和有效性。对于谷歌来说,该语言是解决其目前面临的编译时间长和当今生产中普遍存在的大规模数据处理等问题的解决方案。谷歌想开发一种专注于可扩展性、可读性和并发性的语言,而其他语言无法满足这些要求,于是Go语言诞生了。谷歌的开发者从现有的语言中提取出最简单、最清晰的概念,对这些概念进行改进和组合,最终形成了Go。以处理字符串的高效数据库fmt数据包为例:“fmt包使用类似于C的printf和scanf的函数来实现格式化I/O,动词形式源自C,但更简单。”这是从成功的通用语言(在本例中为C)获取功能并对其进行改进的示例。Go语言的并发机制是基于CSP建模的;使用通道可以避免共享数据的同步错误,这种信息交换方式更简单、更安全。Go语言的另一个重点是简单性。使用Go语言需要在其框架下形成公认的独特代码风格,并在开发不同项目时保持一致,以减少开发过程中配置linting规则和学习不同代码风格的时间;时间是团队工作的一个要素。理论上,这会减少开发者之间在编码风格和编程方法上的差异,就像JavaScript语言包含了很多Eslint的规则一样。方法Go的方法结合了解释型动态语言的编程简单性和编译型静态语言的效率和安全性。它的内置映射定义了原始类型,例如int、byte和string。有指点。另外,用Go语言开发需要注意的一个重要原则就是正交性,这也是函数式方法的基础。Go使用结构体来表示数据,使用用户界面来表示抽象。关于Go语言是否面向对象的争论一直存在,Java开发人员一开始很难理解为什么会有这样的争论。争论的焦点是Go没有类型层次,一般判断是否面向对象的依据是类型层次。有些结构不能被继承,但确实符合对象风格。Go更喜欢组合而不是继承。多态性可以通过接口来实现。满足此接口的任何类型的对象都可以连接到它。除了这些核心概念之外,Go还通过多核处理实现了现代对并发的需求。强并发以goroutines和channels的形式实现。在大型并发程序中,自动垃圾回收作为一种有效的内存管理手段非常重要。单元测试就像使用前缀_test.go一样简单,它在与源文件相同的目录中声明。学习Go语言的原因1.简洁Go语言是以极简主义的方式开发的。没有类或继承。这部分功能在Java和Python等流行语言中被Go中的结构体所取代。Go是强静态类型的,鼓励在所有情况下使用接口。静态类型旨在减少编译错误并使Go更容易学习。虽然众多的固有方法、范例和约定让其他语言(如JavaScript)感到困惑,但Go提供了一种方法作为通用风格指南。从团队的角度来看,单个代码的分析和推理更容易,集成也更顺畅。尽管没有隐式转换,但在语法上花费的精力很少。这使代码更具可读性和更简单。2.快速性静态链接编译器通过编译生成二进制可执行文件,无需处理外部依赖。可执行二进制文件在不使用虚拟机的情况下被编译为本机代码,尽管它们增加了数据大小,但编译速度更快且更便携。另外,如前所述,Go的编译时间和生产时间也很快。由于它的简单性,开发人员的生产力在使用Go语言时得到了关注,即从最初的概念/想法到成品的过程更快。3.并发在Go语言中,并发是一个优先级较高的核心概念,就像使用go关键字给函数加前缀一样简单。Goroutines是简单、轻量级的执行线程。在Go中实现并发非常容易。使用go关键字生成一个新线程,该线程在一组线程中的多个内核之间共享。Goroutines只有几千字节,由Go运行时处理,它将go-routines移动到不同的可运行线程以避免通道被阻塞。这种方法使得异步执行几乎与C/C++一样快。您可以使用通道来控制goroutine的数量,每个通道看起来是同步的,但本质上是异步的。Go的运行时使用可调整大小的有界堆栈,这使堆栈保持较小。内存大小在运行时更改以自动存储堆栈。数十万个goroutine可以在同一个地址空间上运行。存在的问题没有范式这个问题是有争议的。在像Java这样的语言中,泛型类型的使用增加了代码的可重用性,同时保证了类型安全。Go用户问过这个“问题”并思考过。这里的建议可以参考。然而,普遍的观点是使用泛型的好处并没有超过简单性和可读性(没有它们)的好处。竞争条件“不要通过共享内存进行通信;相反,通过通信共享内存。”这种哲学带来了优势,也使Go容易受到竞争条件的影响。由于Go结构的可变性(以及不可变数据结构的缺乏),共享可变数据被强制跨多个并发进程。例如在没有深度复制的情况下将指针发送到通道,固有的可变性质引入了竞争条件。通道可能会改进并发编程,但确实存在通道无能为力的竞争条件风险。但是,GoCLI中内置了一个竞争检测器来帮助检测竞争条件。错误检查错误检查非常明确,没有try...catch语句。在处理错误时,需要改变原有的方法和思维方式,尤其是你在其他语言中习惯的方式。Go开发团队认为减少异常可以防止代码复杂性和返回值重载。这符合其对简单性的需求。但是,在真正发生异常的情况下,可以使用panic和recover来处理异常并恢复。Go还有一个标准的错误接口类型,它使用error()返回一个错误字符串。Go开发人员使用多值返回检查错误值来处理错误。可以从默认生成错误的函数返回错误。通常使用iferr!=nil来识别代码库中的错误。对于某些问题来说太容易了Go的简单性是有代价的。Go的表现力不如JavaScript。没有默认值。抽象和范式的缺乏使得DRY原则的实施更加困难、复杂和不直观。值得注意的一件事是Go还很年轻。开发团队正在考虑使用泛型,随着Go的成熟,还有很大的改进空间。该团队非常努力地不断开发和改进Go。与任何语言一样,Go有其优点和缺点。可以肯定的是,如果有足够多的Gophers(Go程序员)觉得需要某个功能,它就会被实现。虽然看起来好像缺少了一些功能,但从不同的角度来看它可以让您了解如何在Go中实现看似缺少的功能。通常有不同的方法来实现同一件事,对Go更友好的方法。什么时候使用可以说,在现阶段,Go并不能解决所有问题;特别是当它与需要大量抽象的GUI和复杂系统相关时。但是什么语言可以解决所有问题呢?充分利用围棋。如果你觉得这门语言太简单,很难用简洁的方式增加复杂性,你可以使用Go来构建简单的微服务,而不是构建复杂的系统。使用Go作为构建网络和系统的工具,而不是替代更适合手头任务的语言。所以最重要的是使用正确的工具来完成工作。如果这个工具是Go,那么Go应该擅长解决这个问题。切记不要大惊小怪,赶紧去看医生。Go作为一种开源编程语言,可以轻松构建简单、可靠和高效的软件。