On Mon, Apr 12, 2021 at 9:01 AM Luke Wilson <thelukasw...@gmail.com> wrote: > > I've heard several times from members of the community (on Matrix and > possibly on answers) that a simple iteration like > > const mixed = "\b5Ὂg̀9! ℃ᾭG" > for _, c := range mixed { > ... do something with c (but not write to it) > > will actually silently allocate a slice of runes and decode the string into > it, before iteration. I've heard it is done to prevent problems that occur > when a programmer might overwrite data being iterated, which should be a > no-brainer for programmers in general, but sure, whatever. So is it true in > the case for constants? Is it true always, or only when writes occur to the > source string or `c` in that case?
There are different Go compilers, but I'm not aware of any compiler that implements range over a string by first converting the string to a slice of runes. The default Go compiler implements this by calling runtime.decoderune in a loop to fetch each new rune. You can see that code at https://golang.org/src/runtime/utf8.go#L51. There won't be any additional allocation in this statement. > Since hearing of this, I started doing all of my utf-8 iteration of string > runes as such: > > import "unicode/utf8" > str := "Some UTF-8 string." > var i int > for i < len(str) { > r, size := utf8.DecodeRune(str[i:]) > // do something with r... > i += size > } > > Which admittedly is a bit of a burden, and possibly premature optimization if > I'm wrong. But I just think it shouldn't silently allocate a ginormous slice > in the background to iterate the runes of a string I might not read all of, > and especially considering `for i, v := range` should be idiomatic. There is nothing wrong with that code, but it's essentially the same as what the simple range over a string does. > In addition, I wonder if it's the same for other types being iterated? What > if a byte slice for example has some bytes modified during iteration? It must > create a copy, but it shouldn't copy for loops that do not write to the > iterated variable. Ranging over a slice does not create a copy of the slice. However, ranging over an array (not a pointer to an array) does, in the general case, create a copy of the array. That is required by the semantics of range. In some cases that copy can be optimized away. Ian -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXb6GESuPDTHBXR-5bL1Y6G_UoJFG_wD5%2B2S4j1n7VP2g%40mail.gmail.com.