英文:
Return Literal vs Pointer
问题
尝试创建一个切片时遇到了字面量和指针的问题。看起来当我将指针传递给切片的追加操作时,它不喜欢这个。例如,我有一个名为components的包类型,其中包含类型Component。请参考下面的代码。
package components
import ()
type Component struct {
Name string
Element string
Color string
}
func (c *Component) SetName(name string) {
c.Name = name
}
func (c *Component) SetElement(element string) {
c.Element = element
}
func (c *Component) SetColor(color string) {
c.Color = color
}
func (c *Component) GetName() string {
return c.Name
}
func (c *Component) GetColor() string {
return c.Color
}
func (c *Component) GetElement() string {
return c.Element
}
func NewComponent(name string, color string, element string) *Component {
c := &Component{}
c.SetName(name)
c.SetColor(color)
c.SetElement(element)
return c
}
现在,我试图创建一个切片,将所有的组件放入其中,比如Snow、Sand、Sunbeam、Springwater等。
// 使用 Setters 创建 SpringWater 组件
SpringWater := components.Component{}
SpringWater.SetName("SpringWater")
SpringWater.SetColor("Blue")
SpringWater.SetElement("Water")
// 使用构造函数创建 Sand 组件
Sand := components.NewComponent("Sand", "Red", "Earth")
// 错误发生在这里:
compSlice := make([]components.Component, 5)
compSlice = append(compSlice, SpringWater, Sand)
// 错误:无法将类型 (*components.Component) 的 Sand 用作类型 components.Component 进行追加。
现在,如果我直接使用 Setters 并直接设置字段,我可以将其添加到切片中,但是使用方法返回的是一个指针,切片无法接受。我只是不理解并且遇到了困难。请记住,我是新手,基本上是从脚本编程转过来的,所以请原谅我,并且我看到了类似的问题,但是在这个上下文中不理解。
<details>
<summary>英文:</summary>
Trying to make a slice and having problems with literals and pointers. It looks like when appending onto my slice it does not like the fact of being handed a pointer. For instance I have a package type I made called components and holds type Component. See below.
package components
import ()
type Component struct {
Name string
Element string
Color string
}
func (c *Component) SetName(name string) {
c.Name = name
}
func (c *Component) SetElement(element string) {
c.Element = element
}
func (c *Component) SetColor(color string) {
c.Color = color
}
func (c *Component) GetName() string {
return c.Name
}
func (c *Component) GetColor() string {
return c.Color
}
func (c *Component) GetElement() string {
return c.Element
}
func NewComponent(name string, color string, element string) *Component {
c := &Component{}
c.SetName(name)
c.SetColor(color)
c.SetElement(element)
return c
}
Now I am attempting to make a slice to put all my components into I am making spellcasting components like Snow,Sand,Sunbeam,Springwater etc.
//Creating SpringWater Component with Setters
SpringWater := components.Component{}
SpringWater.SetName("SpringWater")
SpringWater.SetColor("Blue")
SpringWater.SetElement("Water")
//Creating Sand Component using the Constructor
Sand := components.NewComponent("Sand", "Red", "Earth")
**ERROR HAPPENS HERE ON COMPLILE:**
compSlice := make([]components.Component, 5)
compSlice = append(compSlice, SpringWater, Sand)
**ERROR: Cannot use Sand as type (*components.Component) as type components.Component in append.**
Now using the Setters and Setting the Fields DIRECT I can add it to a slice however using the method it returns a *pointer and the Slice will not comply. I am just not understanding and having a difficult issue. Keep in mind I am new to programming and basically come from scripting so forgive me on this and have seen similar questions but do not understand in this context.
</details>
# 答案1
**得分**: 1
Go在很多地方隐藏了值和指针之间的差异,但并非所有地方都是如此。
在这种情况下,你需要解引用`Sand`并写成`compSlice = append(compSlice, SpringWater, *Sand)`。
<details>
<summary>英文:</summary>
Go hides the difference between values and pointers in several places, but not everywhere.
In this situation you will have to dereference `Sand` and write `compSlice = append(compSlice, SpringWater, *Sand)`
</details>
# 答案2
**得分**: 1
`component.Component`和`*component.Component`是Go语言中的不同类型。你可能希望将切片定义为`compSlice := make([]*component.Component, 5)`或者`append(compSlice, *SpringWater)`。
你定义的方法都是处理`*component.Component`而不是`component.Component`。
<details>
<summary>英文:</summary>
`component.Component` and `*component.Component` are different types in Go. You're gonna want that slice to be `compSlice := make([]*component.Component, 5)` or `append(compSlice, *SpringWater)`.
The methods you defined all deal with `*component.Component` not `component.Component`.
</details>
# 答案3
**得分**: 1
两个之前的答案都是正确的。
在我的答案中,我将你的代码添加到了`main`包中,并在`main`函数中添加了一些注释,以帮助你理解代码的运行过程。
以下是带有注释的代码:
```go
package main
import (
"fmt"
)
type Component struct {
Name string
Element string
Color string
}
func (c *Component) SetName(name string) {
c.Name = name
}
func (c *Component) SetElement(element string) {
c.Element = element
}
func (c *Component) SetColor(color string) {
c.Color = color
}
func (c *Component) GetName() string {
return c.Name
}
func (c *Component) GetColor() string {
return c.Color
}
func (c *Component) GetElement() string {
return c.Element
}
func NewComponent(name string, color string, element string) *Component {
c := &Component{}
c.SetName(name)
c.SetColor(color)
c.SetElement(element)
return c
}
func main() {
// NewComponent将返回一个*Component类型
// 所以Sand将是一个*Component类型
Sand := NewComponent("Sand", "Red", "Earth")
// 你可以创建一个[]*Component切片
compSlice := make([]*Component, 5)
// 然后将Sand添加到*Component切片中
compSlice = append(compSlice, Sand)
// 结果:将是Sand的引用,它是Component结构体的引用
// [<nil> <nil> <nil> <nil> <nil> 0xc8200121b0]
fmt.Println(compSlice)
// 或者,你可以创建一个[]Component切片
newCompSlice := make([]Component, 5)
// 然后将*Sand的引用添加到其中
newCompSlice = append(newCompSlice, *Sand)
// 结果:将是Component结构体的字面量
// [{ } { } { } { } { } {Sand Earth Red}]
fmt.Println(newCompSlice)
}
另外,你可以在repl.it上运行它。
英文:
Both previous answers are correct.
In my answer, i've added your code to the main
package and i've added some comments in the main function
to help you understanding what is going in your code.
Here is the code with comments:
package main
import (
"fmt"
)
type Component struct {
Name string
Element string
Color string
}
func (c *Component) SetName(name string) {
c.Name = name
}
func (c *Component) SetElement(element string) {
c.Element = element
}
func (c *Component) SetColor(color string) {
c.Color = color
}
func (c *Component) GetName() string {
return c.Name
}
func (c *Component) GetColor() string {
return c.Color
}
func (c *Component) GetElement() string {
return c.Element
}
func NewComponent(name string, color string, element string) *Component {
c := &Component{}
c.SetName(name)
c.SetColor(color)
c.SetElement(element)
return c
}
func main() {
// NewComponent will return a *Component type
// So Sand will we a *Component type
Sand := NewComponent("Sand", "Red", "Earth")
// You can create a slice of []*Component
compSlice := make([]*Component, 5)
// Then append Sand which is a *Component Slice
compSlice = append(compSlice, Sand)
// Result: Will be the reference of Sand which is a reference of Component struct
// [<nil> <nil> <nil> <nil> <nil> 0xc8200121b0]
fmt.Println(compSlice)
// Or, you can create a lice of []Component
newCompSlice := make([]Component, 5)
// Then append the reference of Sand which is *Sand
newCompSlice = append(newCompSlice, *Sand)
// Result: will be the literal Component struct
// [{ } { } { } { } { } {Sand Earth Red}]
fmt.Println(newCompSlice)
}
Also, you can run it in: repl.it
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论