在Go中创建对象

I'm playing around with Go for the first time. Consider this example.

type Foo struct {
    Id int
}

func createFoo(id int) Foo {
    return Foo{id}
}

This is perfectly fine for small objects, but how to create factory function for big objects?

In that case it's better to return pointer to avoid copying large chunks of data.

// now Foo has a lot of fields
func createFoo(id int /* other data here */) *Foo {
    x := doSomeCalc()
    return &Foo{
               Id: id
              //X: x and other data
   }
}

or

func createFoo(id int /* other data here */) *Foo {
    x := doSomeCalc()
    f := new(Foo)
    f.Id = id
    //f.X = x and other data
    return f
}

What's the difference between these two? What's the canonical way of doing it?

The convention is to write NewFoo functions to create and initialize objects. Examples:

You can always return pointers if you like since there is no syntactic difference when accessing methods or attributes. I would even go as far and say that it is often more convenient to return pointers so that you can use pointer receiver methods directly on the returned object. Imagine a base like this:

type Foo struct{}
func (f *Foo) M1() {}

When returning the object you cannot do this, since the returned value is not addressable (example on play):

NewFoo().M1()

When returning a pointer, you can do this. (example on play)

There is no difference. Sometimes one version is the "natural one", sometimes the other. Most gophers would prefere the first variant (unless the second has some advantages).

(Nitpick: Foo{id} is bad practice. Use Foo{Id: id} instead.)