Próbuję podążać za Przysłowie'mem ", aby wartość zerowa była przydatna", ale wprowadź problem z prywatnymi polami na moim strukturze, które są domyślnie domyślnie nil (jak map). Jeśli wartość zerowa mojego struktury ma być przydatna, w pewnym momencie musi zainicjować prywatne pole. Rozważ następującą sytuację, w której chciałbym poznać konstruktor dla Response i przydatne jest wartość zerowej Response. Oczywiście pole bag (która jest map[string]interface{}). Staram się zainicjować pole bag, gdy pojawia się Getter Bag(). Ale w jakiś sposób, gdy odpowiedź kończy się z powrotem w głównej funkcji, moja wartość się zgubiona. Wierzę, że problem jest taki, że inicjalizacja, którą wymyśliłem z zastępującym wskaźnikiem na kopii odpowiedzi, zamiast zmiany tego, co wskazuje wskaźnik. Więc stary wskaźnik wciąż wskazuje na nil, ale nie jestem pewien. Jak poprawnie zainicjować prywatne pole bez konstruktora?

func main() {
    response := getResponse()
    number := response.Bag().Get("NiceNumber")
    fmt.Println(response.Name, "tells me that your nice number today is:", number)
}

func getResponse() (response Response) {
    response = newResponse() // I am trying to do away with this line.
    response.Name = "MyResponse"
    response.Bag().Set("NiceNumber", 100)
    return
}

type Response struct {
    Name string
    bag  Bag
}

func (r Response) Bag() Bag {
    // I have added this piece of code as an attempt to initialize r.bag
    if r.bag == nil {
        r.bag = Bag(make(map[string]interface{}))
    }
    // ---
    return r.bag
}

type Bag map[string]interface{}

func (b Bag) Set(name string, value interface{}) {
    b[name] = value
}

func (b Bag) Get(name string) interface{} {
    return b[name]
}

// This constructor would be deleted if possible.
func newResponse() Response {
    return Response{
        Name: "",
        bag:  Bag(make(map[string]interface{})),
    }
}

Wyjście teraz jest MyResponse tells me that your nice number today is: 100, a kiedy wyjmuję połączenie do konstruktora odpowiedzi, wyjście jest MyResponse tells me that your nice number today is: <nil>.

go
1
Bazzz 15 kwiecień 2021, 11:25

1 odpowiedź

Najlepsza odpowiedź

Możesz zmienić odbiornik metody Bag() do wskaźnika.

func (r *Response) Bag() Bag {
    if r.bag == nil {
        r.bag = Bag(make(map[string]interface{}))
    }
    return r.bag
}

Należy pamiętać, że nadal można wywołać metodę odbiornika wskaźnika w wartości nieskażu wskaźnika, dopóki wartość wynosi adresowalna . Zobacz dokumenty na Wywołania:

Metoda połączenia X.M () jest ważna, jeśli zestaw metody (typu) X zawiera M, a lista argumentów może być przypisana do listy parametrów m. Jeśli X jest adresowalny zestaw metody i & X zawiera m, X.m () jest skróty dla (& x) .m ()

1
mkopriva 15 kwiecień 2021, 08:57