V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
kuanat
V2EX  ›  Go 编程语言

基于 Go 语言谈软件开发效率

  •  
  •   kuanat · 2 天前 · 1345 次点击

    基于 Go 语言谈软件开发效率

    这个帖子的目的不是对比不同编程语言开发效率的高低。

    这个帖子实际上讨论的是以下内容:

    • 软件工程中生产力消耗的占比

    • 语言层面如何改善生产力的利用率

    • Go 有何特殊之处

    0x10 定义和量化生产力

    以代码行数来衡量程序员的产出是非常可笑的指标,同理,以代码复杂度、语法糖支持来评价开发效率也很离谱。

    如果一定要找一个量化指标来评价开发效率,那就是相同开发需求下所消耗的总人力。

    实际上,从理解业务需求开始,到构思实现方式和架构占据了写代码这个过程中绝大部分时间。

    如果考虑团队协作的一般场景,沟通成本又占据了团队人力消耗的一半(个人估计)。

    也就是说,纯代码层面的效率提升即便优化到极致,对于整个开发成本的改善贡献可能远低于 10%。

    0x20 编程语言真正的生产力

    0x21 沟通成本

    能看代码不求人才是最节省沟通成本的方式。

    这里的反例就是互联网与工程化兴起之前的各种语言,需要通过外部工具、团队规则才能保证有效协作的各种脚本语言。

    开发者讨厌屎山的深层原因还是代码不好读、不好改。

    0x22 可读性

    影响可读性的因素很多,这里简单列举几个:

    • 在没有 lsp 辅助的情况下,快速定位到方法的实现,即代码结构组织

    • 隐式控制流,在某些地方隐藏着初始化 init 逻辑,或者有非直接可见的构造、析构方法

    人脑的栈空间是非常有限的,间接、隐藏信息越多,理解成本越高。

    0x23 复用性

    往小的方面说,直接复制其他代码引入项目算是复用。往大的方面说,包引入机制也是复用。

    这里的重点是语言的官方仓库和工具链系统来一致化、规范化这个过程。

    缺少官方包管理、没有官方工具链的各种语言都深受其苦。

    0x24 编程范式与思想

    面向对象的思想就是某个阶段编程语言带来的巨大进步。

    在工程化成为现代语言标配的今天,组合替代继承也是巨大进步。

    关于这一点我在其他帖子里有零散的论述,这里就不展开了。

    0x30 Go 与生产力

    我觉得这个部分是误解最多的,大多数的讨论都没有关注到真正的重点。

    0x31 并发原语

    Go 最重要的贡献之一是基于 chan 的思维模型:Share memory by communication

    日常反复被强调的 goroutine 其实不重要,很多语言也可以有样学样。

    通过 chan/goroutine 的结合,初学者即便不理解 race/signal/thread/shared memory 等等概念,一样可以快速、准确地写出并发逻辑。

    0x32 显式控制流

    没有魔法就是编程语言对开发者最大的尊重。

    Debug 浪费的生产力往往会远超写代码的节省。

    0x33 原生 tls

    在网络编程的时代,原生 tls 才是真正的跨平台。

    技术上跨平台的核心是交叉编译,工程上,保证一条命令构建全平台、全指令集,最后的障碍就是原生 tls 。

    这里节省的是构建系统,一旦有了外部依赖,语言自身的工具链就不够用了。

    0x34 快速编译

    Go 从非常早期就是手搓编译器,而不是转换成 IL 交给通用编译器。缺点是各种语言特性、语法糖都会影响编译器的编写,优点是编译很快。

    人类的多线程能力很差,现实任务频繁上下文切换会极大降低工作效率。

    如果你曾经被 webpack 构建或者 rust 编译支配,你会理解快速编译、即时反馈的意义。

    PS

    这个帖子实际价值也就最后一个章节,还没有展开说。权当抛砖引玉,欢迎斧正。特地放到 Go 节点也是不想让话题沦为口水争论。

    15 条回复    2025-01-04 00:02:54 +08:00
    pursuer
        1
    pursuer  
       2 天前
    要说编译速度快,那脚本不是全秒了。
    按照现在的发展情况看,我怀疑如果 TC39 不开摆,除了 C/C++和 Rust ,其他语言生态最终都会被绑定了浏览器的 JS/TS 占据。即使 JS 是一个槽点很多的语言。JS 的拖累还有 NPM 和 Node 的 Native 扩展。
    ninjashixuan
        2
    ninjashixuan  
       2 天前
    我比较喜欢的一个点是 go 对文件、网络 io 的抽象,写起来很舒服。
    kuanat
        3
    kuanat  
    OP
       2 天前 via Android
    @pursuer #1

    编译速度说的是和编译类型的语言比,而且即使和 vm+jit 类型相比也是快的。

    JS 的整个生态都建立浏览器之上,能力的边界取决于浏览器实现了多少对操作系统的封装。

    如果一定要拿出数据作证的话,js 的份额一直就是在浏览器这个笼子里,别的进不来它也出不去。
    kuanat
        4
    kuanat  
    OP
       2 天前 via Android   ❤️ 1
    @ninjashixuan #2

    这里可能涉及到编程语言的设计哲学,即要在多大程度上暴露或者封装操作系统的抽象。

    在 go 看来,内核 fd 是没有抽象过的 Reader Writer Closer 有用的,这种用接口的实现方式是对“万物皆文件”非常好的诠释。

    同理,socket 相关的抽象也是一样。我个人认为这些都是有意的设计,最初就把跨平台作为目标之一,官方库就对如何封装如何抽象,实现哪些功能做了规划。

    所以很多人说 go 的设计定位是 better c ,但我认为这不是重点,语言层面做个 better c 不难,其他语言一样做得很好。像 c 一样把操作系统底层完全暴露出来是没用的,go 优于 c 同时抢占了部分 c 的市场的原因是它解决了 c 工程化的很多问题。
    zealot0630
        5
    zealot0630  
       2 天前 via Android
    不同语言在不同应用场景下能发挥的功能差距非常大,抛开应用场景谈效率毫无意义。

    没有最好的语言,只有最适合的语言。
    tonyjia87
        6
    tonyjia87  
       2 天前
    好奇的地方,资本对 go 的发力领域是否还有持续投入。 毕竟 java 太多沉淀,rust 太多声音,typescript 太多表现欲。
    pursuer
        7
    pursuer  
       2 天前
    @kuanat 如果真的只在浏览器范围的话,但现在个人 PC 已经成 Electron 宇宙了,移动端也是各种浏览器套壳,如果浏览器开放 Raw socket 和文件系统权限,加上 ServiceWorker 后台运行。感觉现在的工具类应用相当数量都会被 Web 化。

    作为特性,只和特定类型语言比没有意义。快速验证相关现在就是 python/js 这种脚本用的最多。
    kuanat
        8
    kuanat  
    OP
       2 天前 via Android
    @tonyjia87 #6

    对于编程语言来说,资本介入是好事。放在 1990 年可能还好,放到 2025 ,没有靠山的编程语言是没有生命力的。
    uSy62nMkdH
        9
    uSy62nMkdH  
       2 天前
    “相同开发需求下所消耗的总人力” —— 这是一个伪命题没有办法求证
    kuanat
        10
    kuanat  
    OP
       2 天前 via Android
    @pursuer #7

    这个讨论有点偏题了,我想表达的是浏览器相对于整个软件开发领域占比是有限的,这个数据无法支撑你得出“除 c 和 rust 之外被 js 占据”这样的结论。

    我把这个帖子发在 go 而不是程序员节点,目的也是真正讨论工程化和生产力的问题。隔壁帖子的争论 xx 语言的 yy 不好,是建立在真的要把 xx 语言用在所有场景这样一个隐含前提下的。然而现实的人类并不会拿一把锤子就把万物当作钉子。

    所以我不认为某种语言一统天下是个好事,这不符合我的技术哲学认知。
    lesismal
        11
    lesismal  
       2 天前   ❤️ 1
    > Go 最重要的贡献之一是基于 chan 的思维模型:Share memory by communication 。
    > 日常反复被强调的 goroutine 其实不重要,很多语言也可以有样学样。

    chan 挺好, 但本质上相当于个阻塞队列, 即使没有 golang, pipe/cond_t+mutex/sem 之类的传统的进程间通信/线程同步的这些也都能实现类似的阻塞队列组件. 但多进程多线程和这些 syscall 要么阻塞线程要么异步.

    Share memory by communication 更像是从 erlang/actor 拿来的, 但 golang 整个语言本身没有像 erlang 那样纯 actor.
    actor 是个太监模型, actor 之父是为了他们自家电信业务造的 erlang, 电信的那种每个 erlang 进程处理一个连接, 设备进行管理功能也不算复杂不需要连接之间有复杂的交互, 这种场景用 erlang 的进程通信比较简单.
    但纯 actor 并不适合于复杂的业务, 例如连接之间有复杂的交互.
    而且不管哪种 actor, 让一些即使很简单的交互, 或者一些用普通的逻辑处理比较简单的交互, 也都强制必须用通信的方式, 都是需要数据拷贝/调度或者切栈上下文之类的, 这些都带来了额外的性能损失. 性能损失这一点, chan 也是类似的, 简单的有性能需要的功能, 用 chan 未必见得划算.

    runtime 基础之上:
    goroutine 让大家绝大多数时候能写同步代码, 这个解决了传统高并发高性能的 c/c++/java netty/nodejs 等语言的 callback 逻辑不直观和 callback hell 的问题.
    传统的进程间通信/线程同步 syscall 封装组件, 即使实现同步组件, 但阻塞的是进程/线程, 所以不能用 goroutine 与这些 syscall 结合来让大家写同步代码, 所以需要 chan 这种基于 runtime 的轻量阻塞队列实现.

    golang 标准库提供了个基于 runtime 的 cond_t 也可以自己封装下实现 chan 或者类似的组件, 但 chan 已经足够方便了, 我暂时想不到有需要自己搞这个的需要.
    从这些角度讲, 我觉得 goroutine 仍然是最重要的; chan 很好, 但是次之, 因为也有很多场景是不需要甚至不适合用 chan 的.
    kuanat
        12
    kuanat  
    OP
       2 天前 via Android
    @lesismal #11

    你说得非常对,我想了一下,还是 goroutine 更重要一些。

    如果拿 js 来做对比的话,很明显 js 努力的方向一直是用同步的方式写异步逻辑,经过了 promise 到 async/await 的迭代,但 go 这边就很符合直觉。

    另外性能在绝大部分场景不那么重要,可读性、效率和性能之间找个平衡点更重要。现在不是单体应用硬怼 c10k 的时代了。
    tonyjia87
        13
    tonyjia87  
       2 天前
    @kuanat 相信未来会很多公司尝试 go ,共建社区。 现在看比较知名的产物 docker ,kubernetes ,甚至核心成员写的 ollama ,知名的 hugo ,https://github.com/topics/go 前十似乎都是在搞隔离,交付。似乎 infrastructure 才是发力点,可能不准确但是占据多。
    lesismal
        14
    lesismal  
       2 天前
    > 如果拿 js 来做对比的话,很明显 js 努力的方向一直是用同步的方式写异步逻辑,经过了 promise 到 async/await 的迭代,但 go 这边就很符合直觉。

    对对, 非常同意. promise 对于很多人都是个坑, 因为看着是顺序的实际上不是本次 eventloop, 所以遇到 for 循环里的 promise 或者 promise 后面的逻辑, 其实都是违反时序直觉的, 很多新手遇到了 bug 都仍然难搞懂这个. async/await 虽然提供了, 但也是难于理解难于使用, 比 goroutine 自动档差远了
    phoulx
        15
    phoulx  
       1 天前
    #2 #4 毕竟 Go 承接自 Plan 9 ,真正「一切皆文件」的系统
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2872 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 09:00 · PVG 17:00 · LAX 01:00 · JFK 04:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.