Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strings: zero-length string Split()s to non-zero number of substrings #1399

Closed
masiulaniec opened this issue Jan 8, 2011 · 2 comments
Closed

Comments

@masiulaniec
Copy link

package main

import (
        "strings"
        "fmt"
)

func main() {
        fmt.Printf("%#v\t%#v\n", "", strings.Split("", ":", -1))
        fmt.Printf("%#v\t%#v\n", ":", strings.Split(":", ":", -1))
        fmt.Printf("%#v\t%#v\n", "::", strings.Split("::", ":", -1))
}


What is the expected output?

""      []string{}
":"     []string{"", ""}
"::"    []string{"", "", ""}


What do you see instead?

""      []string{""}
":"     []string{"", ""}
"::"    []string{"", "", ""}
@robpike
Copy link
Contributor

robpike commented Jan 8, 2011

Comment 1:

It's working correctly.  Consider splitting space-delimited text using Split("word", "
"): The result should be {"word"}.  Split("w", " ") gives {"w"} and Split("", " ") gives
{""}.  It's all consistent: if the separator doesn't appear in th e text, you get the
input back.

Status changed to WorkingAsIntended.

@masiulaniec
Copy link
Author

Comment 2:

It's consistent indeed; it caused me some troubles streamlining a function:
// getFooNames creates a slice of non-empty names from a colon-separated string.
func getFooNames(s string, emptyOK bool) []string {
        if len(s) == 0 {
                if !emptyOK {
                        panic("empty string")
                }
                return string{}
        }
        names := string.Split(s, ":", -1)
        for n := range names {
                if len(n) == 0 {
                        panic("empty name in a list")
                }
                // ... more validation ...
        }
        return names
}
into a form without the special-case return at the top:
func getFooNames(s string, emptyOK bool) []string {
        names := string.Split(s, ":", -1)
        for n := range names {
                if len(n) == 0 {
                        panic("empty name in a list")
                }
                // ... more validation ...
        }
        if len(names) == 0 && !emptyOK {
                panic("empty list")
        }
        return names
}
I had assumed the loop would not run for empty s, but it did, and panicked.
The assumption is due to me having worked with Perl, where split("") acts differently. 
I've checked out Python's split; it has multiple modes, one of which acts more like
Go's.  Python documentation states:
  Splitting an empty string with a specified separator returns [''].
It might benefit Perl programmers to mention it as well, e.g.:
  Splitting an empty string returns a slice containing empty string as its element.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants