What I'm using right now:
numlines := strings.Count(editor.Text(), "
")
fmt.Print(strconv.Itoa(numlines))
message.SetText(strconv.Itoa(numlines))
This is run whenever a text box is updated. What the most go-like way to do this?
What I'm using right now:
numlines := strings.Count(editor.Text(), "
")
fmt.Print(strconv.Itoa(numlines))
message.SetText(strconv.Itoa(numlines))
This is run whenever a text box is updated. What the most go-like way to do this?
That is perfectly fine. But don't forget that if the last character is not a newline character, you have to add 1 to the number of occurrences, as that will be the number of lines (the last line may not end with a newline).
What we might think is that since the substring you're counting is only a single character (a single rune
), we could create a custom solution counting only the occurrence of this single character (instead of counting substrings). It may look like this:
func countRune(s string, r rune) int {
count := 0
for _, c := range s {
if c == r {
count++
}
}
return count
}
(A for range
on a string
value iterates over its rune
s.)
And testing it (try it on the Go Playground):
fmt.Println(countRune("asdf
asdf
asdf
", '
')) // Prints 3
In practice this won't be faster counting newline characters, as that is a single byte
in UTF-8 encoding, and strings.Count()
is already optimized for counting substrings where the length of the substring is 1:
// Count counts the number of non-overlapping instances of substr in s.
// If substr is an empty string, Count returns 1 + the number of Unicode code points in s.
func Count(s, substr string) int {
if len(substr) == 1 && cpu.X86.HasPOPCNT {
return countByte(s, byte(substr[0]))
}
return countGeneric(s, substr)
}
func countByte(s string, c byte) int // ../runtime/asm_amd64.s
What could improve the performance of this operation (counting lines) is if you would have access to the "internal" byte or rune array of the editor, so you would not have to call its Text()
method, which creates and returns a copy of its content.