返回字面值 vs 指针

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

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 := &amp;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(&quot;SpringWater&quot;)
	    SpringWater.SetColor(&quot;Blue&quot;)
	    SpringWater.SetElement(&quot;Water&quot;)

	    //Creating Sand Component using the Constructor
	    Sand := components.NewComponent(&quot;Sand&quot;, &quot;Red&quot;, &quot;Earth&quot;)

**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&#39;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 (
&quot;fmt&quot;
)
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 := &amp;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(&quot;Sand&quot;, &quot;Red&quot;, &quot;Earth&quot;)
// 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
// [&lt;nil&gt; &lt;nil&gt; &lt;nil&gt; &lt;nil&gt; &lt;nil&gt; 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

huangapple
  • 本文由 发表于 2016年12月22日 04:08:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/41271087.html
匿名

发表评论

匿名网友

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

确定