错误消息中包含数据的惯用方式是什么?

huangapple go评论82阅读模式
英文:

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 &lt;= b.N; i++ {
		f()
	}
}

func BenchmarkG(b *testing.B) {
	for i := 0; i &lt;= b.N; i++ {
		g()
	}
}

func BenchmarkH(b *testing.B) {
	for i := 0; i &lt;= 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.

huangapple
  • 本文由 发表于 2017年7月29日 14:26:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/45386093.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定