Golang slice reference confusion

Multi tool use
package main
import (
"fmt"
)
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i:=0; i<2; i++ {
values = values[:0]
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
https://play.golang.org/p/5x60VfDXbFw
when appending slice,val is expected to be [[0, 1], [1, 2]], but got [[1,2], [1,2]]

add a comment |
package main
import (
"fmt"
)
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i:=0; i<2; i++ {
values = values[:0]
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
https://play.golang.org/p/5x60VfDXbFw
when appending slice,val is expected to be [[0, 1], [1, 2]], but got [[1,2], [1,2]]

That's not the result I saw on go play.
– Ibu
Dec 28 '18 at 3:28
add a comment |
package main
import (
"fmt"
)
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i:=0; i<2; i++ {
values = values[:0]
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
https://play.golang.org/p/5x60VfDXbFw
when appending slice,val is expected to be [[0, 1], [1, 2]], but got [[1,2], [1,2]]

package main
import (
"fmt"
)
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i:=0; i<2; i++ {
values = values[:0]
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
https://play.golang.org/p/5x60VfDXbFw
when appending slice,val is expected to be [[0, 1], [1, 2]], but got [[1,2], [1,2]]


asked Dec 28 '18 at 3:24


preyta
75
75
That's not the result I saw on go play.
– Ibu
Dec 28 '18 at 3:28
add a comment |
That's not the result I saw on go play.
– Ibu
Dec 28 '18 at 3:28
That's not the result I saw on go play.
– Ibu
Dec 28 '18 at 3:28
That's not the result I saw on go play.
– Ibu
Dec 28 '18 at 3:28
add a comment |
3 Answers
3
active
oldest
votes
This happens because the slice val
contains pointers to its subslices, rather than the subslices themselves. In your code, you initially place a pointer to values
in positions val[0]
. Then you modify values
and then set a pointer to values
in val[1]
. But both val[0]
and val[1]
point to the same underlying object (values
), which has been modified.
You can fix this by creating a new values
slice on each iteration of the outer loop, this way each sub slice of val
will be a different slice.
For example:
func main() {
val := make(int, 2)
for i:=0; i<2; i++ {
values := make(int, 0, 100)
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
Output from fmt.Println
:
[0 1] [[0 1] ] // values, val
[1 2] [[0 1] [1 2]] // values, val
[[0 1] [1 2]] // val
add a comment |
slice feature in go:
Slices hold references to an underlying array, and if you assign one
slice to another, both refer to the same array.
The value of slice will be the last time you modify it. Thus, here's two approach to achieve the goal.
use copy
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i := 0; i < 2; i++ {
values = values[:0]
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = make(int, 2)
copy(val[i], values)
fmt.Println(values, val) //
}
fmt.Println(val)
}
new values slice in first for-loop each time
val := make(int, 2)
for i := 0; i < 2; i++ {
values := make(int, 0, 2)
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
add a comment |
You should initialize values in your for loop, values = int{}
code like this:
package main
import (
"fmt"
)
func main() {
var (
valLength = 2
)
val := make(int, valLength)
for i := 0; i < valLength; i++ {
values := int{}
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
And you only change variable valLength
to get any length of slice you want.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53953333%2fgolang-slice-reference-confusion%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
This happens because the slice val
contains pointers to its subslices, rather than the subslices themselves. In your code, you initially place a pointer to values
in positions val[0]
. Then you modify values
and then set a pointer to values
in val[1]
. But both val[0]
and val[1]
point to the same underlying object (values
), which has been modified.
You can fix this by creating a new values
slice on each iteration of the outer loop, this way each sub slice of val
will be a different slice.
For example:
func main() {
val := make(int, 2)
for i:=0; i<2; i++ {
values := make(int, 0, 100)
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
Output from fmt.Println
:
[0 1] [[0 1] ] // values, val
[1 2] [[0 1] [1 2]] // values, val
[[0 1] [1 2]] // val
add a comment |
This happens because the slice val
contains pointers to its subslices, rather than the subslices themselves. In your code, you initially place a pointer to values
in positions val[0]
. Then you modify values
and then set a pointer to values
in val[1]
. But both val[0]
and val[1]
point to the same underlying object (values
), which has been modified.
You can fix this by creating a new values
slice on each iteration of the outer loop, this way each sub slice of val
will be a different slice.
For example:
func main() {
val := make(int, 2)
for i:=0; i<2; i++ {
values := make(int, 0, 100)
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
Output from fmt.Println
:
[0 1] [[0 1] ] // values, val
[1 2] [[0 1] [1 2]] // values, val
[[0 1] [1 2]] // val
add a comment |
This happens because the slice val
contains pointers to its subslices, rather than the subslices themselves. In your code, you initially place a pointer to values
in positions val[0]
. Then you modify values
and then set a pointer to values
in val[1]
. But both val[0]
and val[1]
point to the same underlying object (values
), which has been modified.
You can fix this by creating a new values
slice on each iteration of the outer loop, this way each sub slice of val
will be a different slice.
For example:
func main() {
val := make(int, 2)
for i:=0; i<2; i++ {
values := make(int, 0, 100)
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
Output from fmt.Println
:
[0 1] [[0 1] ] // values, val
[1 2] [[0 1] [1 2]] // values, val
[[0 1] [1 2]] // val
This happens because the slice val
contains pointers to its subslices, rather than the subslices themselves. In your code, you initially place a pointer to values
in positions val[0]
. Then you modify values
and then set a pointer to values
in val[1]
. But both val[0]
and val[1]
point to the same underlying object (values
), which has been modified.
You can fix this by creating a new values
slice on each iteration of the outer loop, this way each sub slice of val
will be a different slice.
For example:
func main() {
val := make(int, 2)
for i:=0; i<2; i++ {
values := make(int, 0, 100)
for j:=0; j<2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
Output from fmt.Println
:
[0 1] [[0 1] ] // values, val
[1 2] [[0 1] [1 2]] // values, val
[[0 1] [1 2]] // val
answered Dec 28 '18 at 3:39


Henry Woody
3,9562824
3,9562824
add a comment |
add a comment |
slice feature in go:
Slices hold references to an underlying array, and if you assign one
slice to another, both refer to the same array.
The value of slice will be the last time you modify it. Thus, here's two approach to achieve the goal.
use copy
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i := 0; i < 2; i++ {
values = values[:0]
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = make(int, 2)
copy(val[i], values)
fmt.Println(values, val) //
}
fmt.Println(val)
}
new values slice in first for-loop each time
val := make(int, 2)
for i := 0; i < 2; i++ {
values := make(int, 0, 2)
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
add a comment |
slice feature in go:
Slices hold references to an underlying array, and if you assign one
slice to another, both refer to the same array.
The value of slice will be the last time you modify it. Thus, here's two approach to achieve the goal.
use copy
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i := 0; i < 2; i++ {
values = values[:0]
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = make(int, 2)
copy(val[i], values)
fmt.Println(values, val) //
}
fmt.Println(val)
}
new values slice in first for-loop each time
val := make(int, 2)
for i := 0; i < 2; i++ {
values := make(int, 0, 2)
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
add a comment |
slice feature in go:
Slices hold references to an underlying array, and if you assign one
slice to another, both refer to the same array.
The value of slice will be the last time you modify it. Thus, here's two approach to achieve the goal.
use copy
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i := 0; i < 2; i++ {
values = values[:0]
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = make(int, 2)
copy(val[i], values)
fmt.Println(values, val) //
}
fmt.Println(val)
}
new values slice in first for-loop each time
val := make(int, 2)
for i := 0; i < 2; i++ {
values := make(int, 0, 2)
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
slice feature in go:
Slices hold references to an underlying array, and if you assign one
slice to another, both refer to the same array.
The value of slice will be the last time you modify it. Thus, here's two approach to achieve the goal.
use copy
func main() {
values := make(int, 0, 100)
val := make(int, 2)
for i := 0; i < 2; i++ {
values = values[:0]
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = make(int, 2)
copy(val[i], values)
fmt.Println(values, val) //
}
fmt.Println(val)
}
new values slice in first for-loop each time
val := make(int, 2)
for i := 0; i < 2; i++ {
values := make(int, 0, 2)
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
answered Dec 28 '18 at 4:01


Bob Fred
1795
1795
add a comment |
add a comment |
You should initialize values in your for loop, values = int{}
code like this:
package main
import (
"fmt"
)
func main() {
var (
valLength = 2
)
val := make(int, valLength)
for i := 0; i < valLength; i++ {
values := int{}
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
And you only change variable valLength
to get any length of slice you want.
add a comment |
You should initialize values in your for loop, values = int{}
code like this:
package main
import (
"fmt"
)
func main() {
var (
valLength = 2
)
val := make(int, valLength)
for i := 0; i < valLength; i++ {
values := int{}
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
And you only change variable valLength
to get any length of slice you want.
add a comment |
You should initialize values in your for loop, values = int{}
code like this:
package main
import (
"fmt"
)
func main() {
var (
valLength = 2
)
val := make(int, valLength)
for i := 0; i < valLength; i++ {
values := int{}
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
And you only change variable valLength
to get any length of slice you want.
You should initialize values in your for loop, values = int{}
code like this:
package main
import (
"fmt"
)
func main() {
var (
valLength = 2
)
val := make(int, valLength)
for i := 0; i < valLength; i++ {
values := int{}
for j := 0; j < 2; j++ {
values = append(values, i+j)
}
val[i] = values
fmt.Println(values, val) //
}
fmt.Println(val)
}
And you only change variable valLength
to get any length of slice you want.
answered Dec 28 '18 at 3:50
yusher
1665
1665
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53953333%2fgolang-slice-reference-confusion%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
yV,K 4 aBdr88,RG8eizAbbwtBlC1B n 6 Q,BzCG 4EUcZWHxW,KZuMix xpIxRgTYaA1PerJ kCrGqttBCP 6ZHPTM9D1TlMSM9W2uaV Vx26sO
That's not the result I saw on go play.
– Ibu
Dec 28 '18 at 3:28