在方法中初始化一个nil指针结构

时间:2014-08-27 06:42:44

标签: pointers struct go

我有一个名为Article的结构,其中有一个名为Image的字段。默认情况下,Image的值为nil。由于Image应仅作为Image.Id保留到数据库,因此我使用bson.BSONGetterbson.BSONSetterjson.Marshaler接口来伪造此行为。

然而,如果我使用其他帮助程序将文件加载到此文件中,则可以在内部使用Image作为io.ReadWriteCloser

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)
}

Playground

现在这种方法存在的问题是,由于ImageImage.SetBSON,因此无法在Image中初始化nil

2 个答案:

答案 0 :(得分:3)

接收器是 passed by value ,包括指针接收器:它是一个副本,并且更改其值不会更改调用该方法的初始指针接收器。

请参阅“Why are receivers pass by value in Go?”。

返回新* Foo的函数Setup可以更好地运行:play.golang.org

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

func main() {
    var f *Foo
    f = SetUp()
}

输出:

Foo: <nil>
Foo: &{Bar:Hello World}

twotwotwo指向一个更好的约定in the comments,即制作包函数foo.New(),如sha512.New()中所示。
但是在这里,您的Setup()功能可能不只是创建*Foo

答案 1 :(得分:1)

bson.Unmarshal在bson数据中遇到Image值时会创建一个指针。因此,一旦我们输入SetBSON i已经是指向Image结构的有效指针。这意味着您没有理由分配Image

package main

import (
    "fmt"
    "io"

    "gopkg.in/mgo.v2/bson"
)

type Article struct {
    Name  string
    Image *Image `bson:"image,omitempty"`
}

type Image struct {
    Id          interface{}
    AlsoIgnored string
    io.ReadWriteCloser
}

func (i *Image) SetBSON(r bson.Raw) error {
    err := r.Unmarshal(&i.Id)
    return err

}

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

func main() {
    backAndForth(Article{
        Name: "It's all fun and games until someone pokes an eye out",
        Image: &Image{
            Id:          "123",
            AlsoIgnored: "test",
        },
    })

    backAndForth(Article{Name: "No img attached"})
}

func backAndForth(a Article) {
    bsonData, err := bson.Marshal(a)
    if err != nil {
        panic(err)
    }

    fmt.Printf("bson form: '%s'\n", string(bsonData))

    article := &Article{}
    err = bson.Unmarshal(bsonData, article)
    if err != nil {
        panic(err)
    }
    fmt.Printf("go form  : %#v - %v\n", article, article.Image)

}

http://play.golang.org/p/_wb6_8Pe-3

输出是:

bson form: 'Tname6It's all fun and games until someone pokes an eye outimage123'
go form  : &main.Article{Name:"It's all fun and games until someone pokes an eye out", Image:(*main.Image)(0x20826c4b0)} - &{123  <nil>}
bson form: 'nameNo img attached'
go form  : &main.Article{Name:"No img attached", Image:(*main.Image)(nil)} - <nil>