英文:
len(string) == 0 or len(string) < 1
问题
在Go语言中,要检查一个字符串是否为空,可以使用以下方法:
len(str) == 0
或者
len(str) < 1
或者
str == ""
基本上只是选择一个运算符==
、<
、!=
,但从性能的角度来看,哪种选项更好呢?
我猜想==
只是进行比较,不像<
或<=
那样迭代遍历值,因此想知道这个问题的最佳实践方法是什么。
英文:
In Go, to check if a string is empty this can be used:
len(str) == 0
or
len(str) < 1
or
str == ""
Basically is just a meter of choosing an operator ==
, <
, !=
, but in terms of performance wish option is better ?
My guess is that ==
just compares and don't iterate through the values like <
or either <==
could do, therefore wondering what is the best approach practice for this.
答案1
得分: 6
由于空字符串是字符串的nil值,你应该与其进行比较。
str == ""
在Go语言中,检查变量是否为nil值以判断其是否为空是一种常用的做法。
就性能而言,没有明显的差异。使用len(str)
是一个函数调用,理论上应该更慢。
编辑:一些证据:
我对以下代码进行了基准测试:
func BenchmarkNil(b *testing.B) {
str := "asd"
cnt := 0
for i := 0; i < b.N; i++ {
if str == "" {
cnt++
}
}
}
使用了三种不同的if语句检查方式:str == ""
、len(str) == 0
和len(str) < 1
。
BenchmarkLenEq-8 2000000000 0.77 ns/op
BenchmarkLenLess-8 2000000000 0.76 ns/op
BenchmarkNil-8 2000000000 0.50 ns/op
对于检查空字符串(str := ""
而不是str := "asd"
),没有明显的差异。检查非空字符串需要更多时间,在那种情况下,nil检查明显更快。
BenchmarkLenEq-8 2000000000 0.34 ns/op
BenchmarkLenLess-8 2000000000 0.33 ns/op
BenchmarkNil-8 2000000000 0.33 ns/op
编辑2:
现在唯一能够相对确定某个操作速度的方法就是进行基准测试。现代CPU是超标量的,所以每条指令一个时钟周期的说法已经不再准确。对空字符串进行比较的基准测试代码在我的4GHz 6700k上以2.94GHz(2.9410^9 op/s)的速度运行,即每次循环迭代少于两个时钟周期。对非空字符串进行nil检查在同一CPU上以2GHz(210^9 op/s)的速度运行。
这意味着nil检查每次循环迭代需要2个CPU周期,而len检查需要3个CPU周期,或者每次循环迭代只需要一条指令来检查空字符串。
英文:
Since the empty string is the nil value of a string, you should compare against that.
str == ""
Checking variables against their nil values to see if they are empty is the Go way of doing this.
In terms of performance, there's no notable difference. Using len(str)
is a function call, so it should in theory be slower.
EDIT: Some evidence:
I benchmarked this code:
func BenchmarkNil(b *testing.B) {
str := "asd"
cnt := 0
for i := 0; i < b.N; i++ {
if str == "" {
cnt++
}
}
}
with the three different checks in the if-statement: str == ""
, len(str) == 0
and len(str) < 1
.
BenchmarkLenEq-8 2000000000 0.77 ns/op
BenchmarkLenLess-8 2000000000 0.76 ns/op
BenchmarkNil-8 2000000000 0.50 ns/op
For checking against an empty string (str := ""
instead of str := "asd"
), there is no measurable difference. Checking against a non-empty string takes more time, and there, the nil check is noticeably faster.
BenchmarkLenEq-8 2000000000 0.34 ns/op
BenchmarkLenLess-8 2000000000 0.33 ns/op
BenchmarkNil-8 2000000000 0.33 ns/op
EDIT2:
The only thing you can do these days to be somewhat sure of how fast something is is to benchmark it. Modern CPU's are superscalar, so one clock cycle per instruction is simply not true anymore. The benchmark code comparing against the empty string ran at 2.94GHz (2.9410^9 op/s) on my 4GHz 6700k, which is less than two clock cycles per loop iteration. The nil check against the non-empty string ran at 2GHz (210^9 op/s) on the same CPU.
This means 2 cpu cycles per loop iteration on the nil check, and 3 on the len check, or a single instruction per loop iteration on the check against the empty string.
答案2
得分: 0
如果你查看X86汇编控制流,你会发现有跳转相等和跳转不等的指令。所以从理论上讲,如果你对Go编译器做一些简单的假设,!=
和<
的执行时间应该是相同的(1个CPU时钟)。
如果你真的对此感兴趣,你可以查看这个答案,并比较它们各自生成的汇编代码。
英文:
If you check X86 Assembly control flows, you see that there are jump on equality and jump on inequality instructions. So in theory and if you make some simple assumptions about Go compiler, !=
and <
would perform the same (1 CPU clock).
If you are really into it, you can see this answer and compare what assembly is produced for each of them.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论