Обработка нуля на уровне метода или конструктора? - PullRequest
0 голосов
/ 27 мая 2018

Стоит ли проверять значения nil в конструкторе, а затем устанавливать неэкспортированное поле структуры или сделать полезным значение структуры struct по умолчанию, проверяя nil на уровне метода?

type Foo struct{}

func (f *Foo) Baz() {}

var DefaultFoo = new(Foo)

type Bar struct {
    Foo *Foo
}

func (b *Bar) Baz() {
    if b.Foo == nil {
        DefaultFoo.Baz()
    } else {
        b.Foo.Baz()
    }
}

или

type Foo struct{}

func (f *Foo) Baz() {}

var DefaultFoo = new(Foo)

type Bar struct {
    foo *Foo
}

func NewBar(foo *Foo) *Bar {
    if foo == nil {
        foo = DefaultFoo
    }
    return &Bar{foo}
}

func (b *Bar) Baz() {
    b.foo.Baz()
}

1 Ответ

0 голосов
/ 28 мая 2018

Я не думаю, что для этого есть «правильный» ответ.

Сказав это, подход, обычно встречающийся в базовых библиотеках Go, позволяет создавать объекты без какого-либо конструктора, используя * 1003.* или zero значений в его полях, а затем заставьте методы иметь логику для использования или возврата полезных значений по умолчанию.

Взгляните на реализацию http.Client, например:

https://github.com/golang/go/blob/master/src/net/http/client.go

Это в основном позволит вам создать нового клиента, просто выполнив:

client := &http.Client{}

Затем вы можете заполнить поля объекта, если хотите переопределить значения по умолчанию, в противном случае он проверитдля nil в различных методах для обеспечения поведения по умолчанию, например:

https://github.com/golang/go/blob/master/src/net/http/client.go#L195

func (c *Client) transport() RoundTripper {
    if c.Transport != nil {
        return c.Transport
    }
    return DefaultTransport
}
...