20

I'm trying to parse git branch names and split them so I can seperate the remote and the branch name

Previously I just split on the first slash:

func ParseBranchname(branchString string) (remote, branchname string) {
    branchArray := strings.Split(branchString, "/")
    remote = branchArray[0]
    branchname = branchArray[1]
    return
}

But I forgot that some folks use slashes in git branch names as well, multiple even!

Right now I'm taking the first element in the slice from the split, then moving every element one done and merging back on the slash:

func ParseBranchname(branchString string) (remote, branchname string) {
    branchArray := strings.Split(branchString, "/")
    remote = branchArray[0]

    copy(branchArray[0:], branchArray[0+1:])
    branchArray[len(branchArray)-1] = ""
    branchArray = branchArray[:len(branchArray)-1]

    branchname = strings.Join(branchArray, "/")
    return
}

Is there a cleaner way to do this?

0

4 Answers 4

32

For Go >= 1.18 see this answer.


For Go < 1.18:

Use strings.SplitN with n=2 to limit the result to two substrings.

func ParseBranchname(branchString string) (remote, branchname string) {
    branchArray := strings.SplitN(branchString, "/", 2)
    remote = branchArray[0]
    branchname = branchArray[1]
    return
}
Sign up to request clarification or add additional context in comments.

2 Comments

Ah, I had tried this but misunderstood the N argument and tried with 0 and 1, now I understand it's not index bound, it's how many results you want to return! This works perfectly, thanks! :)
Yes, I too was confused, coming from Python where str. split() takes an optional maxsplit argument indicating the max number of times to split, not the max number of strings to return.
11

Go 1.18

Use strings.Cut:

[This function] slices s around the first instance of sep, returning the text before and after sep. The found result reports whether sep appears in s. If sep does not appear in s, cut returns s, "", false.

func ParseBranchname(branchString string) (remote, branchname string) {
    remote, branchname, _ = strings.Cut(branchString, "/")
    return
}

(Note that this code snippet is ignoring the third return value, a boolean, that tells whether the separator was found in the input string or not.)

As mentioned in Go 1.18 release notes, Cut "can replace and simplify many common uses of Index, IndexByte, IndexRune, and SplitN". In particular, SplitN with n=2.

Playground — originally posted by @mkopriva in a comment — modified to include an example with Cut: https://go.dev/play/p/bjBhnr3Hg5O

Comments

1

Use strings.Index to find the index of the first / and you split manually with that information:

func ParseBranchnameNew(branchString string) (remote, branchName string) {
        firstSlash := strings.Index(branchString, "/")
        remote = branchString[:firstSlash]
        branchName = branchString[firstSlash+1:]
        return
}

Comparing to your original code:

goos: linux
goarch: amd64
BenchmarkParseBranchname-12         10000000           131 ns/op
BenchmarkParseBranchnameNew-12      300000000            5.56 ns/op
PASS

3 Comments

how dd you benchmarked the method performance? Please give some info
Yes, SplitN will do one extra allocation, which may be needed anyway in a non-simplified version, otherwise the logic is the same as SplitN except this isn't validating the return of Index. ~100ns isn't even noise around the network calls in the context of the OP use case.
@AmitUpadhyay please read this for more details on how to benchmark: dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go
1

One more way could be:

branchArray := strings.Split(branchString, "/")
branchArray = []string{branchArray[0], strings.Join(branchArray[1:], "/")}

remote = branchArray[0]
branchname = branchArray[1]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.