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.

Reply via email to