Golang Go语言中运算符重载有什么实际用途?感觉很鸡肋

发布于 1周前 作者 htzhanglong 来自 Go语言

看到很多人在讨论...但这玩意有啥作用,工作这么多年完全没 get 到


Golang Go语言中运算符重载有什么实际用途?感觉很鸡肋
55 回复

对写 DSL 和 库的人才有意义,能让 API 更语义化,或者语句更像数学公式

更多关于Golang Go语言中运算符重载有什么实际用途?感觉很鸡肋的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


“语句更像数学公式”,就是这个。

golang 要支持了吗?

实现矩阵相乘 ,相加
result := a1 * a2 + a3
而不是
result := sum(mul(a1, a2) , a3)

比如连接
result := s1 + s2
而不是
result := strings.append(s1, s2)

比如实现一个 代替 must( func f() ) 来简化错误处理
result := ()
而不是
result := must(runServer())

比如检测一堆向量是否能形成环
sum := vector(0,0)
for _,v := range vs{
sum += v
}
if sum == vector(0,0) {
// 形成了环
}

而不是

sum := vector(0,0)
for _, v:= range vs{
sum = vectors.add(sum, v)
}
if sum.x == 0 && sum.y == 0 {
// 形成了环
}

举个更简单的例子,无论 C++、Java 、C#、Python ,大家都喜欢用 Class 或 Struct 。这玩意本质上来说,就是对基础数据结构的包装,或者说是语法糖。如果没有 Class 、Struct ,你自己得用一大堆基础数据结构的数组或 List ,来自行管理这些玩意,于是,这个问题,就转换为:

Class 、Struct 有什么实际用途?

运算符重载 我只佩服 kotlin

举个栗子

Python 里 pathlib 拼接路径,
不必用+,不必用 join ,用/

dir / "stem.csv"

非常直觉,高效又易读,
每次我用到都感慨这个重载太漂亮了。

第一次用 Java , 被 BigDecimal interest = loanAmount.multiply(interestRate) 震惊了。。。。。

这个我认为恰恰是个反面例子
在我看来编程语言中 / 就是除法,读出来是除法,做的事情也该是除法
这和向量和矩阵操作这种符合数学直观逻辑的用法很不一样
不过这很 python 就是了,个人感觉 python 总是做一些自以为”自然“的事情

建议看看 scala ,体会下操作符满天飞的感觉。

确实很鸡肋,实用性不强,主要用途是耍帅。


那 numpy 重载切片运算符倒确实还挺自然的

我感觉 python 的三目也有点……

没有操作符重载写点计算的东西简直就是折磨啊

#11 为嘛 / 只能是除法的意思,而不能是分隔符呢?(比如斜杠青年)

那同理,字符串拼接,也不该用 +,而是像拼接矩阵那样,[str1 str2 str3] ?

#10 有没有 greaterEqualThan() 啥的。。

还是叫 greaterThanOrEqualTo()。。

重载运算符跟语言没有关系,支持重载都可以用/拼接路径。

做数学的应该都知道符号是非常不够用的,符号在不同域下定义不一样很正常,
*在初等数学里是乘法,高等里就是卷积了。

而且路径的对象类型不属于数学对象,没有除法
就像,C++里面 IO 流用<<和>>,IO 本身也没有比较大小的必要。

想想确实除了在学校里课上花了好大功夫学了一番,实际工作中并没有怎么用上过。

每次想实践一下,总觉得我写的那些东西还不配让别人迁就我来适应一个新的运算符用法,老老实实 function 加参数就好。

你这种想法极其傲慢。。 键盘上半角符号就这么几个 照你这说法全都只能用于原始的数学含义 那还真出什么运算符重载 全都只支持基础类型就行了

有种给 iostream 左右移的美感(开玩笑)

确实当初下了好大的功夫

在 C++里,比如你写个类,重载一下移位运算符,就可以用左移右移来做输入输出 << >>

C++ 的 filesystem 标准库,也可以用 / 运算符来算路径。比如 std::filesystem::path outputPath = std::filesystem::path(“parent_dir”) / relativePath;

你写一套矩阵库,别人想用起来要是可以直接用 + - * / ,直接 << 输出,可能学习成本就低一点,别人会爽一点。

虽然我确实觉得主要是用来耍帅🤣

那路径里面 windows 的\怎么处理呢,只在 linux 上开发?

说实在的,这就是 shit🕳,连标点都没有

运维人表示 / 显然是路径分割符……话说回来,数学课本里除法写一行用除号 ÷ ,写多行用分数线,斜线并不是主流啊。

严格一点说,大部分语言的运算符即使不支持用户重载,也是已经重载过的了。比如加法 + 严格来说对整数和浮点数是完全不一样的两种操作,像 OCaml 就会区分整数的 + 和浮点数的 +.

所以严格纠结所谓数学上的含义没有意义……

#11 有点教条主义,从实用主义的角度出发工具的发明应该是提高生产效率的,
“黑猫白猫不管什么猫,能让开发人员更加快速的完成开发任务就是好猫”

比如我定义了一个向量类型 P ,有 x/y 两个坐标,向量可以加一个向量到新的位置,就是 p3(x3, y3) = (x1+x2, y1+y2), 如果支持运算符重载,在向量类型定义里我重载掉加法,这样我就只要写 p3 = p1 + p2 就行,而不用写 p3.x = p1.x + p2.x ,p3.y = p1.y + p2.y

说白了还是看业务,总没必要硬着头皮用吧?

这个是语言哲学语言设计的范畴,无所谓好坏,支持运算符重载能找到一堆理由,不支持运算符重载的也有一堆理由。

新语言如 rust 也有通过 trait 来支持运算符重载的

10 个矩阵相乘,你用 golang 写一下吧

高级抽象:除 1 楼提到的 DSL 外,还有场景,例如 ORM



情绪化日志( doge

哈哈,为什么不把表情符号也追加到日志中

C# 里面运算符重载可以实现+注册和-移除方法实现更直观的订阅机制

读出来是除法只能说明一件事,那就是命名不规范不能体现变量或者函数的实际意义。

你用过 Go 的 math/big (或者其他 decimal 包)就知道了,他们的加减乘除是这样的:

<br>func (z *Int) Add(x, y *Int) *Int<br>func (z *Int) Sub(x, y *Int) *Int<br>func (z *Int) Mul(x, y *Int) *Int<br>func (z *Int) Quo(x, y *Int) *Int<br>

本来一行就能写完公式,你用上面的 API 要不断搞中间变量,硬是写成十几二十行,每次写点复杂的计算公式或者 code review ,我就头大,非常想要运算符重载。

比如这个, 运算符就重载了,sesseion.User.filter(User.name == User.nickname | User.age < 15 )

所以,go 是不支持么,理由是什么?然后怎么就推翻了自己

最明显就是向量数学类,能和普通的语法一样加减乘除。
别的似乎也没明显好处。

又想写 equals 了是吧

==啊这种两个数据结构的比较重载一下还是很好用的,也很好读

自定义类要排序的话就必须重载小于号

a + b 本质就是 a.add(b) 的语法糖。
如果平时开发都是以 crud 为主,那确实看起来差别不大。
但如果是以数学计算为主的开发,重载后的±*/之类的符号是比方法名看得更舒服的。

让自定义结构体长的跟内置类型一样,不过个人觉得没必要,妈的 debug 的时候看上去人畜无害的一样结果是个重载

运算符重载有个好处是可以利用运算符的优先级减少括号层数而使代码变得易读。例如创建 sql 的 dsl 时,如果使用 where ((a add b) eq c) and (d eq e) 对比 where a + b == c && d == e 来说,后者更易读

本来没啥感触,您一提到 BigDecimal 我就有点炸裂了。

建议看一下《 effective c++》和《 more effective c++》中运算符重载的相关内容

高级语言有什么用处?写汇编不行吗?😆

你肯定期望能写 “sss” + “ddd” 这种啊…也符合直觉

运算符重载有没有用呢?看楼上感觉没啥大用。
:= 有没有用呢? var variable type 完全满足了,:= 有时还会因为 shadowing 引出一些问题,但你离得开 := 么?

题外话:实际上开始思考这些内容是一个好的开始,先不说重载有没有用,本身这个事情很好……

在Golang(Go语言)中,确实不支持运算符重载这一特性,这是Go语言设计之初就明确的一项原则。Go语言的设计哲学倾向于简洁和明确,避免复杂性,这也是其受到许多开发者喜爱的原因之一。

关于运算符重载的实际用途,在支持该特性的语言中,它确实可以带来一定的便利,比如允许开发者为自定义类型定义特定的运算行为,使得代码在某些场景下更加直观和简洁。然而,这种便利也伴随着潜在的复杂性,比如可能导致代码的可读性和可维护性下降,因为运算符的含义在不同上下文中可能有所不同。

在Go语言中,虽然缺少了运算符重载这一特性,但开发者可以通过方法(methods)来实现类似的功能。例如,为自定义类型定义特定的加法、减法等方法,明确表达操作的意图。这种方式虽然相对冗长一些,但提高了代码的可读性和明确性,有助于减少因运算符重载带来的潜在误解。

因此,虽然运算符重载在某些情况下可能看起来很有用,但Go语言通过其简洁和明确的设计原则,避免了这一特性的引入,从而保持了语言的简洁性和一致性。对于Go语言开发者来说,理解和接受这一设计选择,是掌握Go语言精髓的重要一步。

回到顶部