英文:
What is the idiomatic way to include data in error messages?
问题
我遇到了在Go中将变量嵌入错误消息的不同方法。在下面的示例中,哪种方式是惯用的?是否有更好的选择?
当事情开始出错时,哪种方式更安全?例如,当可用内存非常少时,分配较少字节的选项更可取。
如果我们需要生成大量错误,哪种方式更快?
完整的可运行代码可以在Go Play Space或官方的Go Playground中查看。
func f() error {
return SepError("Sepuled " + strconv.Itoa(n) + " sepulcas " + strconv.Itoa(t) +
" times each")
}
func g() error {
return SepError(strings.Join([]string{
"Sepuled", strconv.Itoa(n), "sepulcas", strconv.Itoa(t), "times each"}, " "))
}
func h() error {
return SepError(fmt.Sprintf("Sepuled %d sepulcas %d times each", n, t))
}
英文:
I’ve encountered different ways to incorporate variables into error messages in Go. In the following example, which way is the idiomatic one? Is there a better alternative?
Which is safer when things start to break? For example, when there is very little memory left available, the option that allocates fewer bytes would be preferable.
Which is faster, in case we need to generate a lot of errors?
The full runnable code can be seen in the Go Play Space or in the official Go Playground.
func f() error {
return SepError("Sepuled " + strconv.Itoa(n) + " sepulcas " + strconv.Itoa(t) +
" times each")
}
func g() error {
return SepError(strings.Join([]string{
"Sepuled", strconv.Itoa(n), "sepulcas", strconv.Itoa(t), "times each"}, " "))
}
func h() error {
return SepError(fmt.Sprintf("Sepuled %d sepulcas %d times each", n, t))
}
答案1
得分: 3
除非你的内存非常小,或者你将生成大量这些错误,否则我不会担心它。就 Go 语言的习惯用法而言,我会选择 h()
选项,因为它更容易阅读。
好处在于可以使用一些简单的基准测试来测试分配、内存使用和速度。
func BenchmarkF(b *testing.B) {
for i := 0; i <= b.N; i++ {
f()
}
}
func BenchmarkG(b *testing.B) {
for i := 0; i <= b.N; i++ {
g()
}
}
func BenchmarkH(b *testing.B) {
for i := 0; i <= b.N; i++ {
h()
}
}
go test -bench . -benchmem
的输出结果如下:
BenchmarkF-8 10000000 169 ns/op 72 B/op 4 allocs/op
BenchmarkG-8 10000000 204 ns/op 120 B/op 5 allocs/op
BenchmarkH-8 5000000 237 ns/op 80 B/op 4 allocs/op
如你所见,f()
是最快的,使用的内存最少,并且与分配最少的函数并列。在我看来,它的可读性的额外成本是不值得的。
英文:
Unless you have very little memory, or are going to be generating a HUGE amount of these errors I wouldn't worry about it. As far as idiomatic Go, I would opt for the h()
option because it is easier to read.
The nice thing here is that allocations, memory used, and speed can be tested with some simple benchmarks
func BenchmarkF(b *testing.B) {
for i := 0; i <= b.N; i++ {
f()
}
}
func BenchmarkG(b *testing.B) {
for i := 0; i <= b.N; i++ {
g()
}
}
func BenchmarkH(b *testing.B) {
for i := 0; i <= b.N; i++ {
h()
}
}
Output of `go test -bench . -benchmem
BenchmarkF-8 10000000 169 ns/op 72 B/op 4 allocs/op
BenchmarkG-8 10000000 204 ns/op 120 B/op 5 allocs/op
BenchmarkH-8 5000000 237 ns/op 80 B/op 4 allocs/op
As you can see, f()
is the fastest, uses the least memory, and is tied for the fewest allocations. It is also, not worth (in my opinion) the additional cost of readability.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论