从 Rust 程序员的早期使用印象看 Go

news2024/9/24 13:24:02

Go vs Rust

img

我在过去的几周开始使用 Go。这是我第一次在一个较大且严肃的项目中使用 Go。之前我对 Go 有过很多了解,并且在研究 Rust 的特性时,曾经使用例子和玩具程序。然而,真正的编程经验是完全不同的。

我认为写写我对它的印象会很有趣。我会尽量避免与 Rust 进行过多比较,但作为我熟悉的语言,比较难免。我应该提前声明对 Rust 有强烈偏爱,但我会尽量客观。

总体印象

使用 Go 编程很舒适。它拥有我在库中想要的一切,而且没有太多棘手的地方。学习它是一个流畅的体验,它是一种设计良好且实用的语言。例如:一旦你熟悉了语法,许多其他语言的习惯用法也能适用于 Go。学会了一些 Go 后,相对容易预测其他功能。有些其他语言知识,我能够阅读 Go 代码并在不进行太多搜索的情况下理解它。

与使用 C/C++、Java、Python 等语言相比,这种方式更少令人沮丧且更高效。然而,它确实感觉像是那一代语言的一部分。它从中吸取了一些教训,我认为它可能是那一代中最好的语言,但它绝对是那一代的一部分。它是一个渐进改进而不是一种完全不同的东西。

明确一下,这不是一种价值判断;在软件工程中,渐进通常是好事。一个很好的例子就是 nil:像 Rust 和 Swift 这样的语言已经移除了 null 的概念,消除了一整类错误。Go 使得它不那么危险:没有空值,它区分了 nil0。但核心思想仍然存在,空指针解引用的常见运行时错误也依然存在。

学习性

Go 的学习曲线非常平缓。我知道这经常被宣传为一个好处,但我真的很惊讶自己是如何迅速地提高生产力的。多亏了语言、文档和工具,我在只有两天的时间里就能编写有趣且可提交的代码。

影响 Go 学习性的一些因素是:

  • Go 是小巧的。很多语言尝试变得小巧,但 Go 确实是小巧的——非常小巧。(这在大多数情况下是一件好事,我对此所需的纪律感印象深刻。)
  • 标准库很好(而且同样很小)。从生态系统中找到并使用库非常容易。
  • 语言中很少有其他语言没有的特性。Go 从其他已有的语言中汲取了很多经验,进行了改进,并将它们整合得很好。它非常努力地避免引入新奇性。

样板代码

Go 代码很快变得非常重复。它缺乏宏或泛型等机制来减少重复(接口对于抽象很好,但对于减少代码重复不太有效)。我经常会有很多函数,除了类型之外几乎都是相同的。

错误处理也导致了重复。许多函数的代码中,有着比有趣代码更多的 if err != nil { return err } 样板代码。

有时,使用泛型或宏来减少样板代码会因为使代码易于编写而受到批评,但使其变得更难阅读。但是我在 Go 中的体验是相反的。复制和粘贴代码非常快速和简单,但阅读 Go 代码却令人沮丧,因为你必须忽略掉太多内容或寻找微妙的不同之处。

我喜欢的东西

编译时间——绝对很快,绝对比 Rust 快得多。但它们实际上并不如我所期望的那么快。对于中大型项目来说,它对我来说感觉上与 C/C++ 差不多或稍快一点点,我原本期望会是即时编译。

Go 协程和通道——使用轻量级语法来创建 Go 协程和使用通道非常好用。这真的展示了语法的强大,这样的细节让并发编程比其他语言更容易。

接口——它们并不是很复杂,但易于理解和使用,在很多场景下都很有用。

if ...; ... { } 语法——能够将变量的作用域限定在 if 语句的主体内是很好的。这与 Swift 和 Rust 中的 if let 有类似的效果,但更通用。(Go 不像 Swift 和 Rust 那样具有模式匹配,所以无法使用 if let。)

测试和文档注释——使用起来很容易。

Go 工具——将所有工具放在一个地方,而不需要在命令行上使用多个工具,这很不错。

垃圾收集器(GC)!——不用考虑内存管理真的让编程变得更容易。

Varargs。

我不喜欢的地方

并没有特定的顺序:

nil 切片 - nil、一个 nil 切片和一个空切片是完全不同的 — 我觉得你只需要其中两种而不是三种。

没有一流的枚举类型 — 使用常量感觉有点落后。

不允许导入循环依赖 — 这会严重限制包的模块化,因为它鼓励将许多文件放在一个包内(或者有很多小的包,如果应该放在一起的文件没有被放在一起,那样也很糟糕)。

switch 语句可能不是完全穷尽的。

for ... range 返回索引/值对 — 获取索引很容易(只需忽略值),但只获取值需要显式处理。对我来说,这似乎是反着的,因为在大多数情况下我需要值而不是索引。

语法:

  • 定义和使用之间的不一致性
  • 编译器的挑剔性(例如,需要或禁止尾逗号);虽然良好的工具可以缓解这个问题,但仍然会有一些让人感到恼火的额外步骤。
  • 使用多值返回类型时,类型需要在 return 语句中使用括号,但在 return 语句中却不需要。
  • 声明结构需要两个关键字(typestruct)。
  • 使用大写字母标记变量是公共还是私有。这有点像匈牙利命名法,但更糟糕。

隐式接口 — 我知道这在我的喜欢列表中,但有时真的很恼人,例如,当尝试找到所有实现某个接口的类型或给定类型实现了哪些接口时。

你不能为不同包中的接收器编写函数,因此即使接口是鸭子类型,也不能为上游类型实现它们,这使得它们变得不太有用。

我已经提到了上面的泛型和宏的缺失。

一致性

作为一名语言设计者和程序员,对我最让人意外的可能是 Go 内置和用户可用性之间的频繁不一致性。许多语言的目标是尽可能地消除魔术,并使内置功能对用户可用。运算符重载就是一个简单但有争议的例子。Go 中有很多魔术!你很容易就会遇到不能做的事情,而这些事情是内置功能可以做的。

以下是一些我注意到的事情:

有很好的语法可以返回多个值和使用通道,但这两者不能同时使用,因为没有元组类型。

有一个用于遍历数组和切片的 for ... range 语句,但是你不能遍历其他集合,因为没有迭代器的概念。

lenappend 这样的函数是全局的,但没有办法使你自己的函数变成全局的。这些全局函数只能用于内置类型。它们也可以是泛型的,尽管 Go 据说没有泛型。

没有运算符重载。这在处理 == 时特别令人恼火,因为这意味着你不能将自定义类型作为映射的键,除非它们是可比较的。这个特性是从类型的结构中派生出来的,无法由程序员覆盖。

结论

Go 是一种简单、小巧且令人愉快的语言。它有一些奇怪的地方,但大多数时候设计得很好。它学习起来非常快,避免了任何在其他语言中不为人知的特性。

Go 是一种与 Rust 完全不同的语言。尽管两者都可以模糊地描述为系统语言或 C 的替代品,但它们有不同的目标和应用场景、不同的语言设计风格和优先级。垃圾回收是一个巨大的不同点。Go 中有 GC 使得语言更简单、更小巧,更容易理解。Rust 中没有 GC 使得它非常快速(尤其是如果你需要确保延迟性,而不仅仅是高吞吐量),并且可以实现在 Go 中不可能的特性和编程模式(或者至少不会牺牲性能)。

Go 是一种编译型语言,具有良好实现的运行时。它很快。Rust 也是编译型语言,但运行时更小。它非常快。在没有其他约束的情况下,我认为选择使用 Go 还是 Rust 是在更短的学习曲线和更简单的程序(这意味着更快的开发速度)之间做出权衡,而 Rust 则非常非常快,并且具有更具表达力的类型系统(这使得您的程序更安全,并意味着更快的调试和错误排查)。

感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java(九)(多线程,线程安全,实现线程的方法,线程同步,线程池,并发和并行,线程的六种状态)

目录 多线程 线程 实现线程的方法 方法一:继承Thread父类 方法二:实现Runnable接口 方法三:Callable接口和FutureTask类来实现 Thread方法 线程安全 线程同步 同步代码块 同步方法 Lock锁 线程池 线程池对象的创建方式一: 线程池处理Runnable任务 线程池处理Cal…

办公软件定制开发在企业发展中的优势|app小程序搭建

办公软件定制开发在企业发展中的优势|app小程序搭建 如今,办公软件已经成为企业日常工作的必需品。很多企业为了提高工作效率和满足自身业务需要,选择定制开发办公软件。下面将介绍定制开发办公软件在企业发展中的优势。 1定制开发办公软件可以满足企业…

uni-app 微信小程序 pdf预览

<div click"getPDF">查看体检报告</div>getPDF() {uni.downloadFile({url: ${this.$baseURL}/file/download?id${this.pdfFileId},//编写在线的pdf地址success: function(res) {const filePath res.tempFilePath;uni.openDocument({filePath: filePath…

每日一练【移动零】

一、题目描述 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 二、题目解析 可以…

Appium自动化如果出现报错怎么办?这么做确实解决问题

解决通过appium的inspector功能无法启动app的原因 在打开appium-desktop程序&#xff0c;点击inspector功能&#xff0c;填写app的配置信息&#xff0c;启动服务提示如下&#xff1a; 报错信息&#xff1a; An unknown server-side error occurred while processing the com…

数据结构(超详细讲解!!)第二十五节 树与森林

1.树的存储结构 和线性表一样&#xff0c;树可以用顺序和链式两种存储结构。 树的顺序存储结构适合树中结点比较“满”的情况。根据树的非线性结构特点&#xff0c;常用链式存储方式来表示树。树常用的存储方法有&#xff1a;双亲表示法、孩子表示法和孩子兄弟表…

Toast UI Editor上传图片到Flask

Toast UI Editor国内文档几乎搜不到&#xff0c;国外文档也写得不是特别项目&#xff0c;没有太多举例的demo。一开始选择使用这个就是因为UI好看。不过看看源码把思路滤清了。 他会给把图片转成Base64&#xff0c;到时候发表单直接丢过去就行了&#xff0c;blob这个参数能拿到…

05 Nacos实战:集成Nacos实现分布式配置中心实现配置动态刷新

上一节介绍了Nacos注册中心的功能,这节介绍下木谷博客中如何使用Nacos作为分布式配置中心。 在第二节搭建项目并运行中讲到创建mugu_nacos_config这个数据库,其中已经包含了木谷博客所需的全部配置,在nacos中也可以查看到,如下: 引入Nacos作为配置中心很简单,步骤如下:…

vue3中的customRef创建一个自定义的 ref对象

customRef 创建一个自定义的 ref&#xff0c;并对其依赖项跟踪和更新触发进行显式控制 小案例: 自定义 ref 实现 debounce <template><div style"font-size: 14px;"><input v-model"text" placeholder"搜索关键字"/><…

flask 上传文件

from flask import Flask, request, render_template,redirect, url_for from werkzeug.utils import secure_filename import os from flask import send_from_directory # send_from_directory可以从目录加载文件app Flask(__name__)#UPLOAD_FOLDER media # 注意&#xff…

【TiDB】TiDB离线方式部署

目录 1 下载TiDB离线组件包 2 安装TiUP 3 合并离线包 4 TIDB 软件和硬件环境建议配置 5 TiDB环境与系统配置检查 6 生成集群初始化配置文件模板 7 执行部署命令 1 检查就能存在的潜在风险 2 手动修复风险 3 部署 TiDB 集群 8 查看TIUP管理的集群情况 9 检查部署的…

[⑥ADRV902x]: 软件系统初始化流程学习

前言 本篇博客主要记录ADRV902x参考软件中对ADRV902x系统的初始化流程&#xff0c;使用API函数来实现transceiver的配置&#xff0c;校准和控制等。官方将整个系统初始化称之为multichip synchronization initialization (MCS) sequence&#xff0c;主要分成PreMcsInit&#x…

数字电源为什么一般用DSP控制,而不能用普通的单片机?

数字电源为什么一般用DSP控制&#xff0c;而不能用普通的单片机&#xff1f; 首先你要清楚&#xff0c;数字电源需要一个芯片具备什么功能&#xff1f; 1 能发PWM波 &#xff0c;并且具备保护关断功能&#xff1b; 电源对PWM发波 要求很高&#xff0c;精度要ns级甚至ps级的&…

易宝OA系统ExecuteSqlForSingle接口SQL注入漏洞复现 [附POC]

文章目录 易宝OA系统ExecuteSqlForSingle接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 易宝OA系统ExecuteSqlForSingle接口SQL注入漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利用文章…

2023极客大挑战-AGRT战队wp

目录 RE Shiftjmp 点击就送的逆向题 幸运数字 ​编辑 砍树 小黄鸭 flower-or-tea mySelf 是男人就来扎针 听说cpp很难&#xff1f; Easymath 寻找初音未来 Rainbow 浪漫至死不渝 ezandroid Pwn nc_pwntools password ret2text write1 ret2libc ezpwn wr…

MicroPython STM32F4 RTC功能使用介绍

MicroPython STM32F4 RTC功能使用介绍 &#x1f516;STM32和ESP32 RTC功能差不多&#xff0c;相关篇《MicroPython ESP32 RTC功能使用介绍》&#x1f4cc;固件刷可参考前面一篇《STM32刷Micropython固件参考指南》&#x1f33f; 相关篇《Micropython STM32F4入门点灯》&#x1…

v-model(双向数据绑定)自动收集数据

v-model 是 Vue 中一个常用的指令&#xff0c;用于实现表单元素与数据的双向绑定。 它的实现原理主要基于以下两个方面&#xff1a; 语法实现&#xff1a; v-model 实际上是 Vue 对 :value 和 input 两个属性的语法糖。当我们在组件中使用 v-model 指令时&#xff0c;Vue 会根…

只需十分钟快速入门Python,快速了解基础内容学习。零基础小白入门适用。

文章目录 简介特点搭建开发环境版本hello world注释文件类型变量常量数据类型运算符和表达式控制语句数组相关函数相关字符串相关文件处理对象和类连接mysql关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源…

数据在内存中的存储练习题

数据在内存中的存储练习题 文章目录 数据在内存中的存储练习题1. 练习一2.练习二3. 练习三4. 练习四5. 练习五6. 练习六7. 总结 1. 练习一 #include <stdio.h>int main() {char a -1;signed b -1;unsigned char c -1;printf("a %d b %d c %d", a, b, c)…

WebSocket快速入门

WebSocket 借鉴&#xff1a; https://blog.csdn.net/weixin_45747080/article/details/117477006 https://cloud.tencent.com/developer/article/1887095 简介 WebSocket 是一种网络传输协议&#xff0c;可在单个 TCP 连接上进行全双工通信&#xff0c;位于 OSI 模型的应用…