Golang开发者是否在重复造轮子?
Golang开发者是否在重复造轮子? 我接触Go语言大约4个月了(算是Go语言新手?!🐶),之前有企业级Java开发经验。
我就直入主题了。二进制文件内部需要依赖一些API,比如日志、网络、安全等。为此开发相应的Go语言等价物来提供内部支持是合理的。
开玩笑地说,我觉得任何用PHP编写且取得成功的项目都应该用Go重写(哈哈)😛
但当你开始关注对象数据库、内容管理系统、规则引擎、消息代理等架构组件时,只要它们可靠、安全且经过时间检验,理想情况下你本不应关心其实现来源。在企业级规模背景下讨论机械共鸣和普遍性似乎没有必要。声明:我并非认为这些概念不必要,而是在上述特定语境下。(先声明以防被喷)
我理解很多Go语言开发者来自Ruby、PHP、Python等背景。Go语言确实像梦想之地,但当你看到用.Net和Java编写的企业系统时,我们真的需要在Go中重新投资和重新发明它们吗?虽然我也用Python编程,但我同样更喜欢Go。
我发现很多项目用Go重新发明轮子,唯一的理由就是Go中尚不存在相应实现。而且这些解决方案都不成熟(这里不具体点名)。确实,成熟是个渐进过程……但这终究是重复造轮子。
编程和软件工程不是一回事。正如我正在发现的,Go是一门很棒的编程语言,我对此感到高兴。但在为商业项目选择架构中的合适组件时,我发现人们倾向于选择用同种语言编写的组件。
我会避免语言比较,因为这并非我的本意,我尊重所有语言(除了那个不该提的语言...猜猜看;既不是GW-Basic也不是Logo...嘿)……但在关注了大量播客和论坛后,我有个印象:人们正在为任何用Go重写的东西欢呼庆祝。
我想自然选择过程会淘汰这类项目,事情本该如此。我认为必须谨慎使用那些仅仅因为是用Go编写的框架,而应该从企业架构的绝对角度来考量组件选择。
未来值得拥有的酷炫功能
我在想是否存在或需要建立一种标准,让每种系统语言都能在同一处理器上共享栈、堆内存,并映射到处理器的内存(待研究)。这将为不同语言的组件打开大门,使其能够以普遍的方式连接,无需网络开销,并消除每种语言都需要囤积和从头重新发明每个框架的需求。这太愚蠢了!
核心观点
语言适合人类阅读和编写代码的方式。它们大多是一个抽象层。好吧,忽略编译优化等因素。但大多数人选择语言并不是基于这些,对吧?
机器并不在乎,最终都是二进制。正因为我们人类无法达成一致,我们才在各种语言中创造了廉价的复制品和相互依赖的层级关系。
好好想想吧!
更多关于Golang开发者是否在重复造轮子?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
hollowaykeanho:
这就像是我们不应该使用天然气灶,而应该倒退到砍柴烧饭
我并不是说我们要回到二进制时代,我的意思是,在企业环境中可以跨语言协作且与语言无关的情况下,重新发明完整的层次结构同样甚至更加荒谬。我认为你误解了那里的意图。无论如何。
更多关于Golang开发者是否在重复造轮子?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
hollowaykeanho:
仅供参考,我之前在其他论坛帮助过一个9岁有志学习Go的小家伙设置Go编译器。你期望他/她能像我们一样提供"企业级"架构吗?
那是编程而非软件工程。我想我确实提到过这两者是有区别的。而且我的讨论背景是企业环境。同样的事情可以用任何编程语言完成,我不明白你在这里想表达什么。不合逻辑。你那位9岁的朋友可以开始学习任何语言而不用考虑这些顾虑。我真的看不出其中的关联。我本不想回复这个,但这简直是个笑话对吧?!
让我们来分析一下各种可能性:
- 如果该包没有API,那么用C语言编写时,你至少需要编写一个Go语言的"C"包装器;如果存在命令行界面,则可以通过os.Exec来调用
- 如果该包提供RESTful API,你可能需要一些便捷的包装函数
- 如果该包使用其他类型的API(例如Postgres),则需要实现Go版本的客户端API
- 如果你不希望承受套接字连接上API的开销,那么最终可能需要从头开始编写该工具的Go版本(例如Redis就是这种情况)
最后,我想指出Oracle数据库的情况。由于他们的JDBC实现不是开源的,Go语言连接Oracle就比较困难。必须使用C包装器的方式,这并不理想。
希望对你有帮助!
除非非Go语言的API…
具体攻击编译器作为结论并拒绝编译器提供的许多内置优化是没有意义的。这相当于要求人们远离Go
亲爱的h*anho先生:
Specifically attacks the compiler as conclusion and reject the many built-in optimization the compiler has to offer makes no sense. That’s equivalent of asking people to stay away from Go ??! 哈哈
That’s equivalent - 传递性、假设和监管。不知道该说什么了。
… 我从未攻击过Go,顺便说一句我很喜欢Go。只是觉得有些库不需要重新发明轮子。看起来你完全忽略了我发帖的初衷,我也检查了用词。虽然我确信你是Go的老手,但也许我们说的不是同一种英语。如果我的任何话语被误解为对Go的攻击,我表示歉意;如果我不喜欢Go,我就不会在这里。只是想像你一样让世界变得更美好!😊
ArjunDhar:
我并非建议回归二进制编程,而是想指出在企业环境中完全重新发明技术层级同样(甚至更为)荒谬,因为不同技术栈本可相互借鉴且语言无关。我想您误解了我的本意。不过没关系。
要么修改你的结论,专门针对"重复造轮子是不良实践"这一点进行论述,否则我的观点依然成立。
专门攻击编译器作为结论,并拒绝利用编译器提供的诸多内置优化是毫无道理的。这相当于让人们完全避开Go语言,严格固守现有的传统工具/实践"作为最终结论"。
在我看来,你的观点就像是说"当我们改用燃气灶时,必须延续燃烧木柴的操作流程,所以我们必须能够像烧木柴那样直接燃烧燃气罐。毕竟,我们都是在通过燃烧获取热量"。
ArjunDhar:
这是编程而非软件工程。我想我确实提到过两者存在区别。而且我的讨论背景是企业环境。这些原则在任何语言中都能实现,我不明白你的论点何在。毫无逻辑。你9岁的朋友可以在不了解技术细节的情况下开始学习任何语言。我真的无法理解其中的关联。本不想回应,但这简直是个笑话吧?!
关键在于,Go语言能够将像9岁孩子那样稚嫩的开发者与你我这样的开发者连接起来,而不会产生大量阅读障碍或编辑困难。这在Python(要么侧重教学要么侧重生产)、C语言(对新手太难)、Ruby(过于神奇)和Java(对初学者太复杂)中都无法实现。既然Go能提供这样的便利性,那么重复发明和代码重复就必然会发生。
这就是为什么我强调应该由使用者根据自身需求来筛选软件包,而不是将特定要求强加给所有创作者。毕竟,Go的源代码本就是最容易阅读和审计的。
附注:那个9岁孩子的事件也让我学到,在任何Go论坛都需要格外谨慎小心,因为你永远不知道是否有未成年人在场。显然,他们不会阅读服务条款。🤷♂️
ArjunDhar:
我认为自然选择过程会淘汰这类项目,这就是事物发展的规律。我认为在使用任何用GO编写的框架时都需要谨慎,因为你正在使用GO,应该从企业架构的绝对角度来考虑组件问题。
你所担忧的情况不仅发生在Go语言中;它在所有语言中都存在。不必为此担心。
由于Go标准化了其代码格式和风格,我个人认为有抱负的开发者在团队中或自行重新造轮子是可以接受的,原因如下:
- 代码易于阅读,可以自由决定集成方案(如自由般自由)
- 让他们通过实践获得必要经验,远比在论坛里滥用他人来完成作业成为"高级开发者"要好得多
- 由于存在现有参考标准,很容易检验他们的努力/诚信/成果
- 你有了参考点,而不是从零开始
过去曾发生过go-bindata事件。从中吸取的教训是:你应该始终审计所集成的库。这也是创建Go模块的典型案例之一。
给他人自由的空间。同样地,你也有权根据需求自由选择。将企业架构思维强加给每个Gopher可能对他人不公平。顺便说一句,我曾在其他论坛帮助过一个9岁的小Gopher设置Go编译器。你期望他/她能像我们一样提供"企业级"架构吗?
ArjunDhar:
语言适合人类读写代码的方式。它们大多是一个抽象层。好吧,忽略编译优化等。但大多数人选择语言不是基于这些,对吧?!
机器不在乎,最终都是二进制。因为我们人类无法达成共识,所以在每种语言中我们都创建了廉价的复制品和相互依赖的层级。
完全荒谬。这种论点就像是我们不应该使用天然气灶,而应该退回到砍柴和堆石生火来做家常菜,因为两者都能生火,都能用,也都能烹饪。
如果有一个编译器能在不需要我阅读厚厚的处理器手册的情况下进行优化,我会选择它。最终,我想要一种既能尽可能接近手动汇编/二进制,又具有人类易于管理和理解的抽象程度的语言。Go是目前最好的选择。
关键句应该是"编程语言只是工具。根据具体问题及其约束条件选择合适的技术"。
这是一个非常深刻的观察,触及了软件工程中一个长期存在的核心问题。作为有Go和Java背景的开发者,你的分析很到位。让我从技术角度来回应几个关键点。
关于重复造轮子的现实考量
在企业环境中,选择用Go重写现有组件确实需要谨慎评估。但有几个技术因素让这种"重复造轮子"在特定场景下是合理的:
1. 性能与资源效率
// 比如用Go重写消息代理可以获得更好的内存控制和并发性能
package main
import (
"net"
"sync"
)
type MessageBroker struct {
connections sync.Map
channels map[string]*Channel
mu sync.RWMutex
}
func (b *MessageBroker) HandleConnection(conn net.Conn) {
// Go的goroutine使得处理大量并发连接更加高效
go b.processMessages(conn)
}
2. 部署简化
Go的静态编译特性消除了运行时依赖,这在容器化部署中优势明显:
// 单一二进制部署 vs Java的JVM+依赖jar
// Dockerfile对比:
// Go: FROM scratch
// Java: FROM openjdk:17-jre
// 这直接减少了攻击面和安全补丁管理成本
3. 团队技能栈统一
当团队主要使用Go时,引入其他语言组件会增加认知负荷和运维复杂度。
关于跨语言组件共享的思考
你提到的跨语言内存共享确实是个有前景的方向。实际上,这方面已经有了一些实践:
使用CGO进行语言间交互
// 通过CGO共享C库的功能,避免重复实现
/*
#include <some_c_library.h>
*/
import "C"
func UseExistingCLibrary() {
result := C.some_c_function()
// 直接使用成熟的C库功能
}
共享内存通信
// 不同进程间通过共享内存通信
import "golang.org/x/sys/unix"
func CreateSharedMemory(key string, size int) ([]byte, error) {
// 创建共享内存段供不同语言组件使用
shmID, err := unix.SysvShmGet(key, size, 0666|unix.IPC_CREAT)
if err != nil {
return nil, err
}
return unix.SysvShmAttach(shmID, 0, 0)
}
企业架构中的务实选择
在企业环境中,我倾向于这样的技术选型策略:
// 核心基础设施:优先考虑成熟度而非语言
type EnterpriseComponent interface {
Reliability() float64 // 可靠性指标
Maturity() int // 成熟度年限
GoNative() bool // 是否为Go原生
}
// 技术选型决策函数
func ShouldUseGoComponent(existing Component, goAlternative Component) bool {
// 如果现有方案足够成熟可靠,即使不是Go也应优先考虑
if existing.Reliability() > 0.99 && existing.Maturity() > 3 {
return false
}
// 对于新业务或性能敏感场景,Go方案可能更合适
return goAlternative.Reliability() > 0.95
}
实际案例:何时选择Go重写
在我经历的项目中,以下情况确实值得用Go重写:
- 高并发中间件 - 如API网关、代理服务
- CLI工具 - 部署简单,启动快速
- 资源受限环境 - 内存占用要求严格的应用
- 团队转型期 - 从动态语言转向静态语言的过渡
你的核心观点很正确:语言是给人用的抽象层。技术决策应该基于业务需求、团队能力和长期维护成本,而不是语言本身的热度。Go确实在很多场景表现出色,但成熟的软件工程应该超越语言偏好,从架构整体最优的角度出发。

