'Split a string only by the first element in golang
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?
Solution 1:[1]
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
}
Solution 2:[2]
Go 1.18
Use strings.Cut
:
[This function] slices
s
around the first instance ofsep
, returning the text before and aftersep
. Thefound
result reports whethersep
appears ins
. Ifsep
does not appear ins
, cut returnss, "", 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
Solution 3:[3]
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
Solution 4:[4]
One more way could be:
branchArray := strings.Split(branchString, "/")
branchArray = []string{branchArray[0], strings.Join(branchArray[1:], "/")}
remote = branchArray[0]
branchname = branchArray[1]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | blackgreen |
Solution 3 | cd1 |
Solution 4 | Amit Upadhyay |