Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go: Am I creating too many values?

Tags:

go

If I have a struct like this

type myStruct struct {
    mystring string
    myint int
}

and if I have a function that returns a new myStruct like this

func New() myStruct {
    s := myStruct{}

    s.mystring = "string"
    s.myint = 1

    return s
}

Because I first store it in the "s" variable before returning it, is my function actually making 2 myStruct values instead of one?

And if so, is it then a better practice to make sure I don't first store it in the variable?

like image 709
the system Avatar asked Dec 20 '12 01:12

the system


2 Answers

The return statement will return a copy of the myStruct object value. If it is a small object then this is fine.

If you intend for the caller to be able to modify this object, and the struct will have methods that use a pointer as the receiver, then it makes more sense to return a pointer to your struct instead:

func New() *myStruct {
    s := myStruct{}

    s.mystring = "string"
    s.myint = 1

    return &s
}

You can see the copy happening when you compare the memory address of value vs pointer return types: http://play.golang.org/p/sj6mivYSHg

package main

import (
    "fmt"
)

type myStruct struct {
    mystring string
    myint    int
}

func NewObj() myStruct {
    s := myStruct{}
    fmt.Printf("%p\n", &s)

    return s
}

func NewPtr() *myStruct {
    s := &myStruct{}
    fmt.Printf("%p\n",s)
    return s
}

func main() {

    o := NewObj()
    fmt.Printf("%p\n",&o)

    p := NewPtr()
    fmt.Printf("%p\n",p)
}


0xf8400235a0 // obj inside NewObj()
0xf840023580 // obj returned to caller
0xf840023640 // ptr inside of NewPtr()
0xf840023640 // ptr returned to caller
like image 181
jdi Avatar answered Oct 06 '22 11:10

jdi


I'm definitely not a Go expert (or even novice :) ), but as @max.haredoom mentioned, you can allocate variables in the function signature itself. In that way, you can also omit the s in the return:

package main

import "fmt"

type myStruct struct {
    mystring string
    myint    int
}

func New() (s myStruct) {
    s.mystring = "string"
    s.myint = 1

    return
}

func main() {
    r := New()
    fmt.Println(r)
}

// Outputs {string 1}

In the examples that I have come across in Effective Go, it does seem to be the most common way of doing things of this nature, but again, I am definitely not an authority on the subject (and will look for additional info on the actual performance).

like image 38
RocketDonkey Avatar answered Oct 06 '22 13:10

RocketDonkey