英文:
Go - append to slice in struct
问题
我正在尝试实现以下两个简单的结构体:
package main
import (
    "fmt"
)
type MyBoxItem struct {
    Name string
}
type MyBox struct {
    Items []MyBoxItem
}
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
    return append(box.Items, item)
}
func main() {
    item1 := MyBoxItem{Name: "Test Item 1"}
    item2 := MyBoxItem{Name: "Test Item 2"}
    items := []MyBoxItem{}
    box := MyBox{items}
    AddItem(box, item1)  // 这是我卡住的地方
    fmt.Println(len(box.Items))
}
我做错了什么?我只是想在box结构体上调用addItem方法并传入一个item。
英文:
I am trying to implement 2 simple structs as follows:
package main
import (
    "fmt"
)
type MyBoxItem struct {
    Name string
}
type MyBox struct {
    Items []MyBoxItem
}
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
    return append(box.Items, item)
}
func main() {
    item1 := MyBoxItem{Name: "Test Item 1"}
    item2 := MyBoxItem{Name: "Test Item 2"}
    items := []MyBoxItem{}
    box := MyBox{items}
    AddItem(box, item1)  // This is where i am stuck
    
    fmt.Println(len(box.Items))
}
What am i doing wrong? I simply want to call the addItem method on the box struct and pass an item in
答案1
得分: 108
嗯... 这是在Go中向切片添加元素时人们最常犯的错误。你必须将结果重新赋值给切片。
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
    box.Items = append(box.Items, item)
    return box.Items
}
另外,你已经为*MyBox类型定义了AddItem方法,所以调用这个方法应该是box.AddItem(item1)。
英文:
Hmm... This is the most common mistake that people make when appending to slices in Go. You must assign the result back to slice.
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
    box.Items = append(box.Items, item)
    return box.Items
}
Also, you have defined AddItem for *MyBox type, so call this method as box.AddItem(item1)
答案2
得分: 21
package main
import (
"fmt"
)
type MyBoxItem struct {
Name string
}
type MyBox struct {
Items []MyBoxItem
}
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
box.Items = append(box.Items, item)
return box.Items
}
func main() {
item1 := MyBoxItem{Name: "Test Item 1"}
items := []MyBoxItem{}
box := MyBox{items}
box.AddItem(item1)
fmt.Println(len(box.Items))
}
英文:
package main
import (
        "fmt"
)
type MyBoxItem struct {
        Name string
}
type MyBox struct {
        Items []MyBoxItem
}
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
        box.Items = append(box.Items, item)
        return box.Items
}
func main() {
        item1 := MyBoxItem{Name: "Test Item 1"}
        items := []MyBoxItem{}
        box := MyBox{items}
        box.AddItem(item1)
        fmt.Println(len(box.Items))
}
Output:
1
答案3
得分: 17
虽然两种答案都是完全正确的。还有两个更改可以进行:
- 摆脱返回语句,因为该方法是为指向结构体的指针调用的,所以切片会自动修改。
 - 没有必要初始化一个空切片并将其分配给结构体。
 
package main
import (
	"fmt"
)
type MyBoxItem struct {
	Name string
}
type MyBox struct {
	Items []MyBoxItem
}
func (box *MyBox) AddItem(item MyBoxItem) {
	box.Items = append(box.Items, item)
}
func main() {
	item1 := MyBoxItem{Name: "Test Item 1"}
	item2 := MyBoxItem{Name: "Test Item 2"}
	box := MyBox{}
	box.AddItem(item1)
	box.AddItem(item2)
	// checking the output
	fmt.Println(len(box.Items))
	fmt.Println(box.Items)
}
英文:
Though both answers are perfectly fine. There are two more changes that can be done,
- Getting rid of the return statement as the method is called for a pointer to the struct, so the slice is automatically modified.
 - There is no need to initialise an empty slice and assign it to the struct
 
    package main    
    
    import (
    	"fmt"
    )
    
    type MyBoxItem struct {
    	Name string
    }
    
    type MyBox struct {
    	Items []MyBoxItem
    }
    
    func (box *MyBox) AddItem(item MyBoxItem) {
    	box.Items = append(box.Items, item)
    }
    
    func main() {
    
    	item1 := MyBoxItem{Name: "Test Item 1"}
    	item2 := MyBoxItem{Name: "Test Item 2"}
    
    	box := MyBox{}
    
    	box.AddItem(item1)
    	box.AddItem(item2)
    
    	// checking the output
    	fmt.Println(len(box.Items))
    	fmt.Println(box.Items)
    }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论