Return Literal vs Pointer

104 Views Asked by At

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.

3

There are 3 best solutions below

0
On

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)

0
On

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.

0
On

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