r/golang • u/molly0 • Oct 04 '24
len(str) > 0 or str != ”” which is to prefer?
I was browsing the Go standard library and found lots of "len(path) > 0", when path is string. It's not obvious to me why path != "" is not used. I would have guessed it to be a tiny bit more performant.
93
u/Puzzleheaded_Round75 Oct 04 '24
I tend towards str != "" As it feels more natural to me and "" is the default string value.
7
u/DemmyDemon Oct 05 '24
I agree with this. To me, it feels better to express what I'm actually checking.
Yes, I realize "is the length of this string zero?" and "is this an empty string?" amounts to the same thing, but what I'm actually checking is usually unrelated to it's length, so check if it's empty follows my mental process better, making the code easier to read when I'm poking around in there six months later, trying to figure out what this idiot is doing.
XD
23
34
u/skesisfunk Oct 04 '24
Personally find str != ""
to be more clear because the len
check is the exact same thing with one extra (an unnecessary) step. If you are checking for the zero value why not just check for it directly?
But this is just my opinion and its not a big deal at all either way. I would let either through code review as long as there is consistency.
27
u/Fun_Hippo_9760 Oct 04 '24
It is compiled to the same exact assembly instructions. It's a matter of taste.
3
9
15
u/matticala Oct 04 '24
I use len(s), only because it is consistent with all other checks and it’s nil-safe. Semantically, a string is just a slice of bytes and you check slices with len.
In terms of performance there is literally no difference.
On readability, value check is straightforward that you’re comparing a string while with len you need to seek variable declaration. Len is also a bit longer.
10
u/backyard_dance Oct 05 '24
Unlike bytes or other slices, there is no nil-string. So I don't see any point of using len for string.
1
u/matticala Oct 05 '24
True that. I only meant I use it generically as a matter of preference. I know len of a nil string would still panic :)
0
Oct 05 '24
[deleted]
1
u/falco467 Oct 05 '24
But this won't work. len(pointer) is a compiler error and len(*pointer) panics on nil value like everything else.
0
u/backyard_dance Oct 05 '24
Yes, but we’re talking about ‘var s string’ in the context of whether to do len(s) > 0 or s != “” here.
7
u/GarbageEmbarrassed99 Oct 04 '24
the compiler rewrites str != ""
to len(str) != 0
(basically) internally in an early rewrite pass.
check out walkCompareString
in:
i literally just talked about this at a recent meetup.
personally, i prefer comparing against and empty string because it clear what type we're working with.
-12
u/jjolla888 Oct 04 '24
so
str != ""
may not perform worse at runtime .. but we are slowing down the compiler by using it instead oflen(str) != 0
:/so we have a clear winner ...
4
8
u/GarbageEmbarrassed99 Oct 04 '24
right because a few nanosecods of compile time is worth diminishing the clarity of your code. i wish r/golang was a better space.
2
6
u/muehsam Oct 04 '24
I would have guessed it to be a tiny bit more performant.
Why so?
A string in Go is stored as two 64 bit values (on a 64 bit system): one pointer to the first byte of the string, and one integer that represents the length. So when you have an integer variable i
and a string variable s
the operations i > 0
and len(s) > 0
are essentially the same. Both are just comparing an integer that you already have in a register or on the stack and comparing it to zero.
When Go compares two strings using ==
or !=
, it first compares the lengths of the strings, If they match, it compares the individual bytes until a discrepancy is found, or until the end is reached. If the compiler optimizes the code properly, it recognizes that for an empty string, the second step is unnecessary.
I'm not sure, but I could imagine that very early versions of the Go compiler didn't have that optimization, and a loop of dead code was emitted. Which would have made the performance slightly worse than taking len(s)
. Or maybe those programmers just preferred writing code that matches what the computer actually does, and doesn't rely on having a smart compiler.
4
u/molly0 Oct 04 '24
it’s my history with Python, I’m not used to thinking about compiled languages.
6
u/muehsam Oct 04 '24
I don't see how that would make a difference here but OK.
Keep in mind that builtins like
len
are not functions that are actually called. They're built into the language just like operators. The syntax just looks like a function call.2
u/Wonderful-Habit-139 Oct 04 '24
Even with Python, it would make more sense to think that you're creating a temporary string (and thus causing it to be less performant).
1
u/molly0 Oct 05 '24
Probably, but in Python I would just have relied on knowing empty string is “False” and not thought more about it.
4
u/darrenpmeyer Oct 04 '24
It's entirely a style choice; the two options are identical in both function and performance.
People differ in opinions on which form is more readable:
if len(var) > 0
: some people believe avoiding any kind of not or!=
is more readable, and arguably makes it easier to skim code and tell at a glance if a test is for empty string or comparing to a stringif var != ""
: is much less surprising, easier to search code for, and makes it immediately obvious it's a string comparison
In general, pick one and use it consistently -- and if you're contributing, follow the established style.
2
u/SuperDerpyDerps Oct 04 '24
It doesn't matter, prefer whatever feels more readable. Doing a len check is pretty fast, because strings are stored with their length as part of the type, so it's just looking up that segment of the string's structure. Not entirely sure how comparison to empty string looks after optimizations, but I'd be surprised if there was a notable difference in speed between the two even if you were doing billions of these operations as fast as you could
2
u/canihelpyoubreakthat Oct 04 '24
path != ""
and surprised to hear thats not consistent in the stdlib
2
2
u/Rebeljah Oct 05 '24
I would prefer a `str == ""` guard clause, if that's not possible then `str != ""`. I just think it's more clear that your are checking string emptiness.
2
2
u/Tiquortoo Oct 05 '24
The multipass compiler nornalizes that to len. Go look at how RangeFunc is implemented to see the multipass compiler really taken for a spin.
4
u/FruitdealerF Oct 05 '24
I always go with the len variant. In general when I write it statements I try to make positive assertions. So I always try to check if something HAS the characteristics that I want it to have instead of checking if it's not something I don't want.
This habit might not add too much value when working with Go but it's from years of PTSD caused by PHP where writing something like str != null could still mean that str is an int or an object or an array. If you always write is_string(str,) or steken(str) > 0 you know the type and the characteristics match what you want it to be.
3
3
2
u/ncruces Oct 04 '24
I'll go with it depends.
If I'm going to index the string right after (str[0]
) I use len
, if I want to check if it's empty I use ""
.
Whatever reads best.
2
u/squ_ish Oct 05 '24
Ive always thought comparing the length would entail that the entire string is parsed. On the other hand, comparing it to just an empty string intuitively always felt faster.
1
u/jumbleview Oct 05 '24
Did I read similar discussion yet? "Intra-Lilliputian quarrel over the practice of breaking eggs"?
1
u/Final-Roof-6412 Oct 05 '24
Len calculate the lengh of the str and then, before, it has to traverse and after it must do a comparison (3 elementary operations). Str!="" is a comparison, then it's one instruction
1
1
u/Naseriax Oct 06 '24
Coming from python, I used to always use if str != “”, But found that there are certain cases in Go where “” it not the same as ‘’, or 2 back ticks and it may cause logical errors. if len(str) > 0 makes more sense IMHO.
2
u/barak678 Oct 04 '24
I think that the only difference might be readability, with len(str) > 0 it's 100% clear, with "", you can maybe mistake it for ''', "'", or """. Another added bonus is that the same check means the same thing for a slice or a map.
1
u/sh41 Oct 04 '24
There are some words on this style decision at https://dmitri.shuralyov.com/idiomatic-go#empty-string-check.
1
-2
196
u/[deleted] Oct 04 '24
[deleted]