修改切片副本中的值,然后将其附加到原始切片中。

huangapple go评论68阅读模式
英文:

Modify values in copy of slice then append to original slice

问题

编写一个函数,用于复制一个切片并修改副本中的项目值,然后将副本附加到原始切片。代码似乎不仅修改了切片的副本,还修改了原始切片。

以下是要翻译的代码:

import "fmt"

type Item struct {
	name   string
	number int
}

func main() {
	names := []string{"a", "b"}
	numbers := []int{1, 2}

	items := []*Item{}

	for _, name := range names {
		item := &Item{name: name}
		items = append(items, item)
	}

	for n, i := range numbers {
		if n > 0 {
			fmt.Println(n, "make a copy of the items")
			itemCopies := make([]*Item, len(items))
			copy(itemCopies, items)

			fmt.Println(n, "set the numbers on the copies")
			for _, item := range itemCopies {
				item.number = i
			}

			fmt.Println(n, "append the copies to the original")
			items = append(items, itemCopies...)
		} else {

			fmt.Println(n, "first pass set all the items to the first number")
			for _, item := range items {
				item.number = i
			}
		}
	}

	for n, i := range items {
		fmt.Printf("%d %+v\n", n, *i)
	}
}

实际看到的输出结果:

0 {name:a number:2}
1 {name:b number:2}
2 {name:a number:2}
3 {name:b number:2}

预期看到的输出结果:

0 {name:a number:1}
1 {name:b number:1}
2 {name:a number:2}
3 {name:b number:2}

你可以在Go Playground上运行这段代码。

英文:

Writing a function to copy a slice and modify the values on the items in the copy of the slice then append the copy to the original. It appears the code is not only modifying the copy of the slice but also the original slice.

Go Playground

import "fmt"

type Item struct {
	name   string
	number int
}

func main() {
	names := []string{"a", "b"}
	numbers := []int{1, 2}

	items := []*Item{}

	for _, name := range names {
		item := &Item{name: name}
		items = append(items, item)
	}

	for n, i := range numbers {
		if n > 0 {
			fmt.Println(n, "make a copy of the items")
			itemCopies := make([]*Item, len(items))
			copy(itemCopies, items)

			fmt.Println(n, "set the numbers on the copies")
			for _, item := range itemCopies {
				item.number = i
			}

			fmt.Println(n, "append the copies to the original")
			items = append(items, itemCopies...)
		} else {

			fmt.Println(n, "first pass set all the items to the first number")
			for _, item := range items {
				item.number = i
			}
		}
	}

	for n, i := range items {
		fmt.Printf("%d %+v\n", n, *i)
	}
}

What I'm actually seeing

0 {name:a number:2}
1 {name:b number:2}
2 {name:a number:2}
3 {name:b number:2}

What I expected to see

0 {name:a number:1}
1 {name:b number:1}
2 {name:a number:2}
3 {name:b number:2}

答案1

得分: 1

@JimB是对的,你复制了指针。

我建议在结构体Item中定义一个copy函数来创建一个副本。

package main

import "fmt"

type Item struct {
	name   string
	number int
}

func (it *Item) copy() *Item {
	return &Item{
		name:   it.name,
		number: it.number,
	}
}

func main() {
	names := []string{"a", "b"}
	numbers := []int{1, 2}

	items := []*Item{}

	for _, name := range names {
		item := &Item{name: name}
		items = append(items, item)
	}

	for n, i := range numbers {
		if n > 0 {
			fmt.Println(n, "复制items")
			itemCopies := make([]*Item, len(items))

			for j := 0; j < len(items); j++ {
				itemCopies[j] = items[j].copy()
			}
			fmt.Println(n, "在副本上设置数字")
			for _, item := range itemCopies {
				item.number = i
			}

			fmt.Println(n, "将副本追加到原始items")
			items = append(items, itemCopies...)
		} else {

			fmt.Println(n, "第一次遍历将所有items设置为第一个数字")
			for _, item := range items {
				item.number = i
			}
		}
	}

	for n, i := range items {
		fmt.Printf("%d %+v\n", n, *i)
	}
}

希望对你有帮助!

英文:

@JimB was right you copy pointers,

I suggest define a copy function belong Struct Item to new a duplicate

package main
import &quot;fmt&quot;
type Item struct {
name   string
number int
}
func (it *Item) copy() *Item {
return &amp;Item{
name:   it.name,
number: it.number,
}
}
func main() {
names := []string{&quot;a&quot;, &quot;b&quot;}
numbers := []int{1, 2}
items := []*Item{}
for _, name := range names {
item := &amp;Item{name: name}
items = append(items, item)
}
for n, i := range numbers {
if n &gt; 0 {
fmt.Println(n, &quot;make a copy of the items&quot;)
itemCopies := make([]*Item, len(items))
for j := 0; j &lt; len(items); j++ {
itemCopies[j] = items[j].copy()
}
fmt.Println(n, &quot;set the numbers on the copies&quot;)
for _, item := range itemCopies {
item.number = i
}
fmt.Println(n, &quot;append the copies to the original&quot;)
items = append(items, itemCopies...)
} else {
fmt.Println(n, &quot;first pass set all the items to the first number&quot;)
for _, item := range items {
item.number = i
}
}
}
for n, i := range items {
fmt.Printf(&quot;%d %+v\n&quot;, n, *i)
}
}

huangapple
  • 本文由 发表于 2023年4月13日 23:52:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76007450.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定