! [Image courtesy-https://xkcd.com/138/] (https://raw.githubusercontent.com/studygolang/gctt-images/master/uh-oh-is-in-go-slice-of-pointers/1.png) Go makes it easy to manipulate Slice and other basic data structures. It is a happy thing to use Golang in most cases for people from the dreaded world of pointers to C + +. For **js/python** users, Golang is no different than syntax. However, **js/pyhon** users or Go beginners always encounter the use of pointers. The following scenario is what they might encounter. # # Scenario Assuming such a scenario, you need to load a slice of the string pointer containing the data, ' []*string{} '. Let's look at a piece of code. "' Gopackage mainimport (" FMT "" StrConv ") func main () {//declares a string pointer to a slice listofnumberstrings: = []*string{}//pre-declares a variable, This variable stores this data before adding the data to the slice var numberstring string//from 0 to 9 of the loop for I: = 0; I < 10; i++ {//Add ' # ' before the number, construct a string numberstring = Fmt. Sprintf ("#%s", StrConv. Itoa (i)//Add a numeric string to the slice listofnumberstrings = append (listofnumberstrings, &numberstring)}for _, N: = Range listofnumberstrings {fmt. Printf ("%s\n", *n)}}//The original article code has a Bug, the translator made a change. The example code above generates a number from 0 to 9. We use ' StrConv. The Itoa ' function converts each number to a corresponding string representation. Then add the ' # ' character to the head of the string and finally add the target slice using the ' append ' function. Run the code snippet above and you get the output "➜sample go run main.go#9#9#9#9#9#9#9#9#9#9 ' > What is the situation?>> why I only see the last number ' #9 ' being output??? I'm pretty sure I added the other numbers to this list!>> let me add debug code to this sample program. "' Gopackage mainimport (" FMT "" StrConv ") func main () {//declares a string pointer to a slice listofnumberstrings: = []*string{}//pre-declares a variable, This variable stores this data before adding the data to the slice var numberstring string//from 0 to 9 of the loop for I: = 0; I < 10; i++ {//Add ' # ' before the number, construct a string numberstring = Fmt. Sprintf ("#%s", StrConv. Itoa (i)) fmt. Printf ("Adding number%s to the slice\n", numberstring)//Adds a numeric string to the slice listofnumberstrings = append (Listofnumberstrings, &numberstring)}for _, N: = Range listofnumberstrings {fmt. Printf ("%s\n", *n)} "the output of the modal code is" "➜sample Go run main.goadding number #0 to the sliceadding number #1 to the sliceadding Number #2 to the sliceadding number #3 to the sliceadding number #4 to the sliceadding number #5 to the sliceadding number #6 to the sliceadding number #7 to the sliceadding number #8 to the sliceadding number #9 to the slice "> I see them added to the. .>>, how did this happen to me? >> $@#! Ah ah ah Ah!! Friends, relax, let's see what happened.You. "' Govar numberstring string ' numberstring here will be assigned to the heap, let's assume that its memory address is ' 0x3af1d234 '. [Numberstring on the stack at address 0x3af1d234] (https://raw.githubusercontent.com/studygolang/gctt-images/master/uh-oh-is-in-go-slice-of-pointers/2.png) " Gofor I: = 0; I < 10; i++ {numberstring = fmt. Sprintf ("#%s", StrConv. Itoa (i)) listofnumberstrings = append (Listofnumberstrings, &numberstring)} "Now let's loop from 0 to 9. # # # First iteration [i=0] In this iteration, we generate the string ' #0 ' and store it in the variable ' numberstring '. [Numberstring stored at 0x3af1d234 with content "#0"] (Https://raw.githubusercontent.com/studygolang/gctt-images/master/uh-oh-is-in-go-slice-of-pointers/3.png) Next, We get the address of the ' numberstring ' variable (' &numberstring '), which is ' 0x3af1d234 ' and then add it to the ' listofnumberstrings ' slice. ' Listofnumberstrings ' should now be like the same! [Listofnumberstrings slice with value 0x3af1d234] (https://raw.githubusercontent.com/studygolang/gctt-images/master/uh-oh-is-in-go-slice-of-pointers/4.png) # # # The second iteration [I=1] We repeat the above steps. This time, we generated the string ' #1 ' and stored it in the same variable ' numberstring '. [Numberstring stored at 0x3af1d234 with content "#1"] (https://raw.githubusercontent.com/studygolang/gctt-images/master/ Uh-oh-is-in-go-slice-of-pointers/5.png) Next, we take the address of the ' numberstring ' variable (&numberstring), the value of the address equals ' 0x3af1d234 ', It is then added to the slice of ' listofnumberstrings '. ' Listofnumberstrings ' should now look like this:! [Both items in the slice BOTH with values 0x3af1d234.] (https://raw.githubusercontent.com/studygolang/gctt-images/master/uh-oh-is-in-go-slice-of-pointers/6.png) Hopefully it's beginning to make you understand what's going on. This slice currently has two variables. But these two variables (subscript 1 and subscript 2) all store the same value: ' 0x3af1d234 ' (the memory address of ' numberstring '). However, keep in mind that at the end of the second iteration, the string stored in ' numberstring ' is ' #1 '. Repeat the above steps until the end of the iteration. After the last iteration, the string stored in ' numberstring ' is ' #9 '. Now let's see what happens when we try to output every element stored in a slice by using the ' * ' operator to dereference it. ' Gofor _, N: = Range listofnumberstrings {fmt. Printf ("%s\n", *n)} ' ' because the value of each variable stored in the slice is ' 0x3af1d234 ' (as shown in the example above), the dereference element will return the value that exists on that memory address. From the last iteration, we know that the last value stored is ' #9 ', so the output is just like the following. The ' ➜sample go Run main.go#9#9#9#9#9#9#9#9#9#9 ' # # solution has a fairly simple way to solve this problem: modify the position of the variable ' numberstring ' declaration. "' Gopackage MainiMport ("FMT" "StrConv") func main () {listofnumberstrings: = []*string{}for I: = 0; i <; i++ {var numberstring stringnu mberstring = FMT. Sprintf ("#%s", StrConv. Itoa (i)) listofnumberstrings = append (listofnumberstrings, &numberstring)}for _, N: = range Listofnumberstrings {FMT . Printf ("%s\n", *n)}return} "We declare this variable in the ' for ' Loop. How did this happen? Each iteration of the loop, we force re-declaring the variable ' numberstring ' on the stack, giving him a new, different memory address. > * * *: Here is not allocated on the stack, through the escape analysis ' Go build-gcflags '-M ', you can know ' &numberstring ' escaped to the heap. The original author explains this because the author uses the C-language perspective to look at the problem. There are similar problems in the C language, but it is possible to interpret the above code by enforcing a new variable on the stack. In Golang, the above code is interpreted by the compiler's escape analysis. We then update the variable with the generated string and add its address to the slice. In this case, each element in the slice stores a unique memory address. The output of the above code will be "➜sample go run main.go#0#1#2#3#4#5#6#7#8#9" and I hope this article will help some people. The idea of me writing this article was because of my experience with a junior engineer in a company where he met a similar scenario and was completely out of the way. This reminds me of a situation where I fell into a similar trap when I was a former C-language junior engineer at the company. > Ps. If you come from a wonderful world of pointers in C + + ... Honestly, you've come across this error (and learn from it)! ;)
via:https://medium.com/@nitishmalhotra/uh-ohs-in-go-slice-of-pointers-c0a30669feee
Author: nitish Malhotra Translator: Magichan proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
453 Reads