How to check a string is empty?

18,840 views
Skip to first unread message

Lambda

unread,
Apr 8, 2010, 6:27:54 AM4/8/10
to golang-nuts
Some functions that return string will return empty string when
something is wrong.
To check a string is empty or not, there are several ways:
len(str) == 0 or
str == ""
...
Which one is preferred?

Kees

unread,
Apr 8, 2010, 7:01:33 AM4/8/10
to golang-nuts
I prefer

str+"badgerbadgerbadger" == "badgerbadgerbadger"

But that's just me I suppose :-)

Joan Miller

unread,
Apr 8, 2010, 7:44:34 AM4/8/10
to golang-nuts
It's faster and simple to use
str == ""

Before of that, you could want to remove blank spaces:
strings.TrimSpace(str)

chris dollin

unread,
Apr 8, 2010, 7:48:06 AM4/8/10
to Joan Miller, golang-nuts
On 8 April 2010 12:44, Joan Miller <pelo...@gmail.com> wrote:
It's faster

Than what? len(str) == 0?

Why do you think so?
 
and simple to use str == ""

 It's certainly more /obvious/ to use str == "". (I'd expect
the compiler to compile that into the same code as
len(str)==0, myself.)

--
Chris "allusive" Dollin

Joan Miller

unread,
Apr 8, 2010, 7:56:57 AM4/8/10
to golang-nuts

On 8 abr, 11:48, chris dollin <ehog.he...@googlemail.com> wrote:


> On 8 April 2010 12:44, Joan Miller <pelok...@gmail.com> wrote:
>
> > It's faster
>
> Than what? len(str) == 0?
>
> Why do you think so?

Because it calls to the function `len` to get its size. Using a call
to a function will be something slower than using directly the code to
get the result.

Alexander Surma

unread,
Apr 8, 2010, 8:03:32 AM4/8/10
to Joan Miller, golang-nuts
> Because it calls to the function `len` to get its size. Using a call
> to a function will be something slower than using directly the code to
> get the result
Actually, this doesn't have to be true. As far as a I know, go-strings
are (internally) a struct containing the length of the string and a
rune-array. So comparing to strings (i.e. traversing both strings) is
considerably *slower* than comparing length. But I'd assume that the
go developers were smart enough to make a length-comparison before
traversing both strings.

Surma

chris dollin

unread,
Apr 8, 2010, 8:06:41 AM4/8/10
to Joan Miller, golang-nuts
On 8 April 2010 12:56, Joan Miller <pelo...@gmail.com> wrote:


On 8 abr, 11:48, chris dollin <ehog.he...@googlemail.com> wrote:
> On 8 April 2010 12:44, Joan Miller <pelok...@gmail.com> wrote:
>
> > It's faster
>
> Than what? len(str) == 0?
>
> Why do you think so?
Because it calls to the function `len` to get its size.

len is a builtin. I don't expect any function calls to be involved.

... func strlen( s string ) int { return len(s) } ...

... 8g -S len.go > xxx ... xvi xxx ...

Can't see a function call there.

--
Chris "allusive" Dollin

peterGo

unread,
Apr 8, 2010, 9:51:11 AM4/8/10
to golang-nuts
Joan,

On Apr 8, 7:56 am, Joan Miller <pelok...@gmail.com> wrote:
> Because it calls to the function `len` to get its size. Using a call
> to a function will be something slower than using directly the code to
> get the result.

The question is about the facts, not your opinion.

if len(s) == 0 {
}

MOVL s+-32(SP),BX
CMPL BX,$0
JNE ,6

Peter

peterGo

unread,
Apr 8, 2010, 10:00:27 AM4/8/10
to golang-nuts
Lambda,

In Go, the underlying representation of a string includes a byte array
to store the string; the byte array includes its length. len(str) ==
0 is very efficient. For example.

var s string = ""
if len(s) == 0 {
}

translates to something like

MOVL s+-32(SP),BX
CMPL BX,$0
JNE ,6

Peter

peterGo

unread,
Apr 8, 2010, 10:11:48 AM4/8/10
to golang-nuts
Kees,

On Apr 8, 7:01 am, Kees <kees.varek...@gmail.com> wrote:
> I prefer
>
> str+"badgerbadgerbadger" == "badgerbadgerbadger"

That is a very inefficient way to test for len(str) == 0

Strings are immutable. A new string is created, which is the
concatenation of the variable str and the string literal. Then, if the
string lengths are equal, which they would be for var str = "", each
byte of the UTF-8 string is compared for equality. There are calls to
runtime.catstring and runtime.cmpstring.

Peter

Joan Miller

unread,
Apr 8, 2010, 10:13:52 AM4/8/10
to golang-nuts

On 8 abr, 13:51, peterGo <go.peter...@gmail.com> wrote:
> Joan,
>
> On Apr 8, 7:56 am, Joan Miller <pelok...@gmail.com> wrote:
>
> > Because it calls to the function `len` to get its size. Using a call
> > to a function will be something slower than using directly the code to
> > get the result.
>
> The question is about the facts, not your opinion.

Those facts are valid for whatever another function. This case is an
exception because `len` is a builtin function.

chris dollin

unread,
Apr 8, 2010, 10:17:44 AM4/8/10
to peterGo, golang-nuts
On 8 April 2010 15:11, peterGo <go.pe...@gmail.com> wrote:
Kees,

On Apr 8, 7:01 am, Kees <kees.varek...@gmail.com> wrote:
> I prefer
>
> str+"badgerbadgerbadger" == "badgerbadgerbadger"

That is a very inefficient way to test for len(str) == 0

I think it was supposed to be a (shell-inspired?) joke.

--
Chris "stess on 'supposed'" Dollin

Peter Bourgon

unread,
Apr 8, 2010, 10:22:42 AM4/8/10
to golang-nuts
On Thu, Apr 8, 2010 at 4:13 PM, Joan Miller <pelo...@gmail.com> wrote:
>> The question is about the facts, not your opinion.
> Those facts are valid for whatever another function. This case is an
> exception because `len` is a builtin function.

Even if len weren't a builtin function, testing s == "" requires an
O(n) traversal of s, which can easily be more costly than a function
call. Further, in many languages, even the == operator by itself may
have the same cost as a function call.

chris dollin

unread,
Apr 8, 2010, 10:22:45 AM4/8/10
to Joan Miller, golang-nuts

This case is the one that was being discussed.

(And there are more built-in functions than `len`.)

(And compilers are pretty much free to inline /any/ function if
they [1] think that will produced better results. Just because it
/looks/ like a function call doesn't mean it's implemented with
CALL and RETURN instructions, or that it uses any extra
stack, or that there are any transfers of control.)

--
Chris "mov pc, r14" Dollin

peterGo

unread,
Apr 8, 2010, 10:27:36 AM4/8/10
to golang-nuts
Chris,

On Apr 8, 7:48 am, chris dollin <ehog.he...@googlemail.com> wrote:
> It's certainly more /obvious/ to use str == "". (I'd expect
> the compiler to compile that into the same code as
> len(str)==0, myself.)

For 6g, you are going to be disappointed. If you ask for a string
comparison, that's what you get: a call to runtime.cmpstring.

Peter

On Apr 8, 7:48 am, chris dollin <ehog.he...@googlemail.com> wrote:

chris dollin

unread,
Apr 8, 2010, 10:28:18 AM4/8/10
to peter....@gmail.com, golang-nuts
On 8 April 2010 15:22, Peter Bourgon <peterb...@gmail.com> wrote:
On Thu, Apr 8, 2010 at 4:13 PM, Joan Miller <pelo...@gmail.com> wrote:
>> The question is about the facts, not your opinion.
> Those facts are valid for whatever another function. This case is an
> exception because `len` is a builtin function.

Even if len weren't a builtin function, testing s == "" requires an
O(n) traversal of s,

Not if s has its length exposed. A single comparison will do
(and in fact that's what 8g does).

For general string equality, yes; the cost of /fetching data/
may dwarf the cost of calling a function, especially if it's
in the cache already.

--
Chris "allusive" Dollin

peterGo

unread,
Apr 8, 2010, 10:45:58 AM4/8/10
to golang-nuts
Alexander,

On Apr 8, 8:03 am, Alexander Surma <alexander.su...@googlemail.com>
wrote:


> As far as a I know, go-strings
> are (internally) a struct containing the length of the string and a
> rune-array.

In Go, strings are encoded, in variable length form, as UTF-8, which
stored in a byte array. Therefore, the length of the string is
actually the number of bytes used to store the UTF-8 string, not the
number of Unicode characters or code points.

Peter

On Apr 8, 8:03 am, Alexander Surma <alexander.su...@googlemail.com>
wrote:

Joan Miller

unread,
Apr 8, 2010, 10:57:09 AM4/8/10
to golang-nuts
var s string = ""
if s == "" {
}

translates to something like:

0007 (test2.go:5) LEAQ s+-16(SP),SI
0008 (test2.go:5) LEAQ (SP),DI
0009 (test2.go:5) MOVSQ ,
0010 (test2.go:5) MOVSQ ,

Joan Miller

unread,
Apr 8, 2010, 11:00:45 AM4/8/10
to golang-nuts
Sorry, it's larger:

0007 (test2.go:5) LEAQ s+-16(SP),SI
0008 (test2.go:5) LEAQ (SP),DI
0009 (test2.go:5) MOVSQ ,
0010 (test2.go:5) MOVSQ ,

0011 (test2.go:5) LEAQ go.string.""+0(SB),SI
0012 (test2.go:5) LEAQ 16(SP),DI
0013 (test2.go:5) MOVSQ ,
0014 (test2.go:5) MOVSQ ,
0015 (test2.go:5) CALL ,runtime.cmpstring+0(SB)
0016 (test2.go:5) MOVL 32(SP),BX
0017 (test2.go:5) CMPL BX,$0
0018 (test2.go:5) JNE ,6
---
Ok. Using `len(str)==0` is a lot of faster than `str == ""`

peterGo

unread,
Apr 8, 2010, 11:03:39 AM4/8/10
to golang-nuts
Peter,

If the lengths of the strings are the same, s == "some string"
comparison time is O(n), where n is the number of bytes for variable
length UTF-8 encoded strings. If the string lengths differ, then only
the string lengths need be compared for equality; string comparison
time is zero.

For example, runtime.cmpstring.
http://golang.org/src/pkg/runtime/string.cgo

Peter

On Apr 8, 10:22 am, Peter Bourgon <peterbour...@gmail.com> wrote:

Joan Miller

unread,
Apr 8, 2010, 11:05:29 AM4/8/10
to golang-nuts

On 8 abr, 14:00, peterGo <go.peter...@gmail.com> wrote:

> Lambda,
>
> In Go, the underlying representation of a string includes a byte array
> to store the string; the byte array includes its length.  len(str) ==
> 0 is very efficient.  For example.
>
> var s string = ""
> if len(s) == 0 {
>
> }
>
> translates to something like
>
> MOVL    s+-32(SP),BX
> CMPL    BX,$0
> JNE     ,6
>

It's something more but it follows being shorter than the another one

0005 (test.go:5) JMP ,7
0006 (test.go:5) JMP ,16
0007 (test.go:5) MOVL s+-8(SP),BX
0008 (test.go:5) CMPL BX,$0
0009 (test.go:5) JNE ,6

chris dollin

unread,
Apr 8, 2010, 11:07:55 AM4/8/10
to peter....@gmail.com, golang-nuts
On 8 April 2010 15:28, chris dollin <ehog....@googlemail.com> wrote:
On 8 April 2010 15:22, Peter Bourgon <peterb...@gmail.com> wrote:
On Thu, Apr 8, 2010 at 4:13 PM, Joan Miller <pelo...@gmail.com> wrote:
>> The question is about the facts, not your opinion.
> Those facts are valid for whatever another function. This case is an
> exception because `len` is a builtin function.

Even if len weren't a builtin function, testing s == "" requires an
O(n) traversal of s,

Not if s has its length exposed. A single comparison will do
(and in fact that's what 8g does).

It looks like I have to eat at least some of my words; vim had
kindly started me off part-way down the assembler file. I
think the preamble is all string copying and the core is the
single comparison, but at the moment ...


--
Chris "mr face, meet mr egg" Dollin

peterGo

unread,
Apr 8, 2010, 11:25:07 AM4/8/10
to golang-nuts
Lanbda,

On Apr 8, 6:27 am, Lambda <stephenh...@gmail.com> wrote:

> Some functions that return string will return empty string when
> something is wrong.

That should rarely be true in Go. Go allows for multiple return
values, therefore, the "comma err" or "comma ok" idiom is used; the
error is returned separately.

For example, from the strconv package,

func Unquote(s string) (t string, err os.Error)

Unquote interprets s as a single-quoted, double-quoted, or backquoted
Go string literal, returning the string value that s quotes. (If s is
single-quoted, it would be a Go character literal; Unquote returns the
corresponding one-character string.)

If there is an error then err != nil.

Peter

On Apr 8, 6:27 am, Lambda <stephenh...@gmail.com> wrote:

Russ Cox

unread,
Apr 8, 2010, 2:50:44 PM4/8/10
to Lambda, golang-nuts

The one that makes the code clear.
If I'm about to look at element x I typically write
len(s) > x, even for x == 0, but if I care about
"is it this specific string" I tend to write s == "".

It's reasonable to assume that a mature compiler will compile
len(s) == 0 and s == "" into the same, efficient code.
Right now 6g etc do compile s == "" into a function call
while len(s) == 0 is not, but that's been on my to-do list to fix.

Make the code clear.

Russ

Tong Sun

unread,
Jul 28, 2015, 9:36:32 PM7/28/15
to golang-nuts, steph...@gmail.com, r...@golang.org
Any updates/conclusion on this? 

To check if a string is empty or not, better use
> len(str) == 0 or
> str == ""

Thanks

Caleb Spare

unread,
Jul 28, 2015, 9:39:14 PM7/28/15
to Tong Sun, golang-nuts
"Using whichever makes the code clear" still applies. FWIW I think
that 'str == ""' is more clear almost 100% of the time.

They compile to the same code these days, so it doesn't have
performance implications.

-Caleb

Tong Sun

unread,
Jul 28, 2015, 9:43:03 PM7/28/15
to Caleb Spare, golang-nuts
Thanks. So, 

`str == ""` for test empty, and 
`str != ""` for not empty, right?

tita...@gmail.com

unread,
Jul 29, 2015, 11:46:57 AM7/29/15
to golang-nuts, steph...@gmail.com
I think comparing to an empty string is silly, just check its len. len(s) makes it clear you are checking its length and not comparing its content.

Staven

unread,
Jul 29, 2015, 11:53:41 AM7/29/15
to golang-nuts
On Wed, Jul 29, 2015 at 08:46:38AM -0700, tita...@gmail.com wrote:
> I think comparing to an empty string is silly, just check its len. len(s)
> makes it clear you are checking its length and not comparing its content.

I agree. Using len(s) == 0 also accounts for all other strings of length 0.

Giulio Iotti

unread,
Jul 29, 2015, 12:05:57 PM7/29/15
to golang-nuts, ces...@gmail.com, sunto...@gmail.com
On Wednesday, July 29, 2015 at 4:43:03 AM UTC+3, Tong Sun wrote:
Thanks. So, 

`str == ""` for test empty, and 
`str != ""` for not empty, right?

Right. And in practice only the first one, as you will use early return ;)

-- 
Giulio Iotti

Paul Borman

unread,
Jul 29, 2015, 12:29:50 PM7/29/15
to Giulio Iotti, golang-nuts, ces...@gmail.com, sunto...@gmail.com
I regularly encourage using s == "" rather than s == len(0), though both are valid and are equivalent.  Using s == "" makes it very clear you are looking at a string and not at a slice (yes, yes, a string could be considered an immutable slice of bytes).  On slices you have to be clear about s == nil vs s == len(0) as while a nil slice has a length of 0, not all slices of length 0 are nil (unlike strings, where all strings of length 0 are "")

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dan Kortschak

unread,
Jul 29, 2015, 5:49:03 PM7/29/15
to Staven, golang-nuts
?

Kiki Sugiaman

unread,
Jul 29, 2015, 7:08:38 PM7/29/15
to golan...@googlegroups.com
My take: flip a coin, move on. This is one of the choices which won't
determine the success/failure of the software you ship. It won't be a
performance bottleneck either if you choose wrong.
Reply all
Reply to author
Forward
0 new messages