101
yb2313 89 天前
bang dream it's my go
|
102
Trim21 89 天前
@yu1miao #100 你把上面那个也改成 var buf io.ByteWriter = &Buffer{} 就看出区别了
var _ IBuffer = (*Buffer)(nil) var _ io.ByteWriter = (*Buffer)(nil) func write(w io.ByteWriter) { for i := byte(0); i < 10; i++ { _ = w.WriteByte(i) } } func writeGeneric[W io.ByteWriter](w W) { for i := byte(0); i < 10; i++ { _ = w.WriteByte(i) } } func BenchmarkExtract(b *testing.B) { var buf io.ByteWriter = &Buffer{} for i := 0; i < b.N; i++ { write(buf) } } func BenchmarkExtra(b *testing.B) { var buf IBuffer = &Buffer{} for i := 0; i < b.N; i++ { writeGeneric(buf) } } BenchmarkExtract-16 1000000000 4.872 ns/op 0 B/op 0 allocs/op BenchmarkExtra-16 1000000000 25.43 ns/op 0 B/op 0 allocs/op |
103
Trim21 89 天前
@yu1miao #100 准确的说这里有 6 种情况,你 benchmark 跑一下就能看出来泛型实现的问题了。
这里跟 writeGeneric 直接传结构体的性能跟用接口,并且编译器没有进行 devirtualize 是相同的,并不会像你说的那样专门生成一个 writeGeneric(w *Buffer) error 如果你传进去的是一个接口,调用开销直接就翻倍了。 func Benchmark_interface_0(b *testing.B) { var buf = &Buffer{} for i := 0; i < b.N; i++ { write(buf) } } func Benchmark_interface_1(b *testing.B) { var buf io.ByteWriter = &Buffer{} for i := 0; i < b.N; i++ { write(buf) } } func Benchmark_interface_2(b *testing.B) { var buf IBuffer = &Buffer{} for i := 0; i < b.N; i++ { write(buf) } } func Benchmark_generic_0(b *testing.B) { var buf = &Buffer{} for i := 0; i < b.N; i++ { writeGeneric(buf) } } func Benchmark_generic_1(b *testing.B) { var buf io.ByteWriter = &Buffer{} for i := 0; i < b.N; i++ { writeGeneric(buf) } } func Benchmark_generic_2(b *testing.B) { var buf IBuffer = &Buffer{} for i := 0; i < b.N; i++ { writeGeneric(buf) } } Benchmark_interface_0-16 232742709 5.139 ns/op 0 B/op 0 allocs/op Benchmark_interface_1-16 434387566 2.794 ns/op 0 B/op 0 allocs/op Benchmark_interface_2-16 85636600 14.67 ns/op 0 B/op 0 allocs/op Benchmark_generic_0-16 85636600 13.97 ns/op 0 B/op 0 allocs/op Benchmark_generic_1-16 54496902 24.23 ns/op 0 B/op 0 allocs/op Benchmark_generic_2-16 49954623 24.91 ns/op 0 B/op 0 allocs/op |
104
maybeok 89 天前
我是 PHP 转 go 的,go 让我觉得很麻烦的一点就是每次修改都不能热更新,需要我重新 run 一次,不像 PHP 改完刷新就行了。 我觉得 go 是世界上最好的语言,但 PHP 是宇宙第一的语言,yyds
|
105
hez2010 89 天前
@james122333 问题就在于错误/异常这种东西恰好不应该通过多返回值来解决,因为错误和正常是互斥的。go 硬是把一个需要用 sum types 表达的东西用 product types 表达了出来。
正确设计应该返回 Result | Error 作为结果,而不是 Result * Error 。 |
107
james122333 89 天前
@hez2010
重点在於不是所有错误都是不可接受的 照这种情况便要在接近的外层捕获 而单返回值也不能够表示 return nil, nil 这种状况 所以我才提那个例子 可以处理 error 也可以 panic |
108
james122333 89 天前
|
109
Trim21 89 天前
@james122333 #108
你说的这几个其实都不是问题。 单返回值也可以表示 return nil, nil , 只要这个 Result 是 *T | Error 就行。你是想的 int | Error 不能 nil ,nil ,但你定义为 *int | Error 肯定可以 nil ,nil 。nil 也是一个 *int 。 所以 rust 的解决方法是加了一个 ? 操作符,在 Err 时候直接把 Err 返回上层,中止当前函数。 |
110
ashong 89 天前
Go 起码能看懂, 近几天看 tauri 源码,rust 整个就是天书
|
111
james122333 89 天前 via Android
|
112
Trim21 89 天前
@james122333 #111 除非你在 err!=nil 的时候也返回了一个 T ,否则我们说的 Result 是涵盖了你说的这种情况的。
|
113
jiangzm 89 天前
Go 有一部分奇怪的语法只是为了标新立异,同样是 Google 推出的语言 Dart 就正常很多,类 C 的语法很容易让其他语言开发者上手。
|
114
dwu8555 89 天前
Hacknews 上最频繁出现的就是 Golang 和 Postgres
|
115
jackblack369 89 天前
历经过 javaer 、pythoner ,这月开始入坑的 gopher ,感觉挺好,个人挺喜欢
|
116
james122333 88 天前 via Android
|
117
molika 88 天前
只能说交叉编译太爽了. 心智负担比 rust 低. 二进制包完爆 py
写起来习惯就好了. |
118
xiaocaiji111 88 天前
做业务没 java 爽,其他还行,当然也得看是什么业务,电商这些,国内只有字节在搞吧,也能搞,但是不太爽。
|
120
Trim21 88 天前 via Android
@james122333 这里说的 Result 是提供判断是否为 Error 还是为 result 的能力的,同时判断两者为 nil 就是非 error 并且 *T 为 nil 的情况啊?
这里说的这个 Result 在 go 里是不存在的,不是结构体那样的东西。结构体和多返回值是一回事。 |
121
james122333 88 天前 via Android
|
123
Trim21 87 天前 via Android
@james122333 有啊
|
124
zizon 87 天前
v2 上也很多喷时政的,想明白了就释然了
|