Initialize a nil pointer struct in method

bod*_*ser 3 struct pointers go

I have a struct called Article which has a field called Image. Per default Image has value nil. As Image should be only persisted as Image.Id to database I use the bson.BSONGetter, bson.BSONSetter and json.Marshaler interfaces to fake this behavior.

However internally it is possible to use Image as an io.ReadWriteCloser if I load a file onto this with some other helper.

package main

import (
    "io"
    "fmt"

    "gopkg.in/mgo.v2"
)

type Article struct {
    Name  string
    Image *Image
}

type Image struct {
    Id interface{}

    io.ReadWriteCloser
}

func (i *Image) SetBSON(r bson.Raw) error {
    i = &Image{}

    return r.Marshal(i.Id)
}

func (i *Image) GetBSON() (interface{}, error) {
    return i.Id
}

func (i *Image) MarshalJSON() ([]byte, error) {
    return json.Marshal(i.Id)
}
Run Code Online (Sandbox Code Playgroud)

Playground

The problem with this approach now is that it is not possible to initialize Image in Image.SetBSON as Image is nil.

Von*_*onC 6

The receiver is passed by value, including the pointer receiver: it is a copy, and changing its value doesn't change the initial pointer receiver on which the method is called.

See "Why are receivers pass by value in Go?".

A function Setup returning a new *Foo would work better: play.golang.org

func SetUp() *Foo {
    return &Foo{"Hello World"}
}

func main() {
    var f *Foo
    f = SetUp()
}
Run Code Online (Sandbox Code Playgroud)

Output:

Foo: <nil>
Foo: &{Bar:Hello World}
Run Code Online (Sandbox Code Playgroud)

twotwotwo points to a better convention in the comments, which is to make a package function foo.New(), as in sha512.New().
But here, your Setup() function might do more than just creating a *Foo.

  • 或者,遵循标准库的约定, `NewFoo() *Foo` (或者如果模块名为 `foo`,则只是 `foo.New()`,就像 `crypto/sha512` 导出 `sha512.New( )`)。 (2认同)