Dokumenty Wprowadzenie poświęcić wiele akapitów do wyjaśnienia różnicy między new()
i make()
, ale w praktyce, można tworzyć obiekty w zakresie lokalnym i ich zwrotu.
Dlaczego miałbyś używać pary alokatorów?
Rzeczy, które możesz z make
tym zrobić , nie możesz zrobić w żaden inny sposób:
To trochę trudniejsze do uzasadnienia new
. Najważniejsze, co ułatwia, to tworzenie wskaźników do typów niekompozytowych. Dwie poniższe funkcje są równoważne. Jest tylko trochę bardziej zwięzłe:
func newInt1() *int { return new(int) }
func newInt2() *int {
var i int
return &i
}
m := map[string]int{}
zamiastm := make(map[string]int)
? nie ma też potrzeby wstępnego przydzielania rozmiaru.Go ma wiele sposobów alokacji pamięci i inicjowania wartości:
&T{...}
,&someLocalVar
,new
,make
Alokacja może również nastąpić podczas tworzenia literałów kompozytowych.
new
może być użyty do przydzielenia wartości takich jak liczby całkowite,&int
jest nielegalny:Różnicę między
new
imake
można zobaczyć, patrząc na następujący przykład:Załóżmy, że Go nie ma
new
imake
ma wbudowaną funkcjęNEW
. Wówczas przykładowy kod wyglądałby tak:*
Byłoby obowiązkowe , więc:Tak, łączenie
new
imake
w jednej wbudowanej funkcji jest możliwe. Jest jednak prawdopodobne, że pojedyncza wbudowana funkcja doprowadziłaby do większego zamieszania wśród nowych programistów Go niż posiadanie dwóch wbudowanych funkcji.Biorąc pod uwagę wszystkie powyższe punkty, wydaje się bardziej odpowiednie
new
imake
pozostać oddzielne.źródło
int
został utworzony.make(Point)
imake(int)
w tych ostatnich 2 linie?make
funkcja przydziela i inicjuje tylko obiekt typu plasterek, mapa lub chan. Podobnienew
jak pierwszy argument jest typem. Ale może również wymagać drugiego argumentu, rozmiaru. W przeciwieństwie do new, zwracany typ make jest taki sam jak typ argumentu, a nie wskaźnik do niego. Przydzielona wartość jest inicjalizowana (nie jest ustawiona na zero, jak w nowym). Powodem jest to, że plasterek, mapa i chan to struktury danych. Muszą zostać zainicjowane, w przeciwnym razie nie będą przydatne. To jest powód, dla którego new () i make () muszą być inne.Poniższe przykłady z Effective Go wyjaśniają:
źródło
new([]int)
po prostu przydziela pamięć dla [] int, ale nie inicjuje, więc po prostu zwracanil
; nie wskaźnik do pamięci, ponieważ jest bezużyteczny.make([]int)
przydziela i inicjuje, aby można było z niego skorzystać, a następnie zwrócił adres.new(T)
- Przydziela pamięć i ustawia ją na wartość zerową dla typu T .. ..to jest
0
dla int ,""
dla łańcucha inil
dla typów odniesienia ( plasterek , mapa , chan )Zauważ, że przywoływane typy są tylko wskaźnikami do niektórych podstawowych struktur danych , które nie zostaną utworzone przez
new(T)
Przykład: w przypadku wycinka , podstawowa tablica nie zostanie utworzona, w ten sposób
new([]int)
zwraca wskaźnik do zeramake(T)
- Przydziela pamięć dla odnośnych typów danych ( plasterek , mapa , chan ), a także inicjuje ich podstawowe struktury danychPrzykład: w przypadku wycinka podstawowa tablica zostanie utworzona z określoną długością i pojemnością
Pamiętaj, że w przeciwieństwie do C, tablica jest prymitywnym typem w Go!
Biorąc to pod uwagę:
make(T)
zachowuje się jak składnia literałowo-złożonanew(T)
zachowuje się jakvar
(gdy zmienna nie jest zainicjowana)Uruchom program
Dalsza lektura:
https://golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make
źródło
Musisz
make()
tworzyć kanały i mapy (i wycinki, ale można je również tworzyć z tablic). Nie ma alternatywnego sposobu na ich wykonanie, więc nie można usunąćmake()
z leksykonu.Co do
new()
tego, nie znam żadnego bezpośredniego powodu, dla którego potrzebujesz go, kiedy możesz użyć składni struct. Ma jednak unikalne znaczenie semantyczne: „utwórz i zwróć strukturę ze wszystkimi polami zainicjowanymi do wartości zerowej”, co może być przydatne.źródło
Oprócz wszystkiego wyjaśnionego w Effective Go , główna różnica między
new(T)
i&T{}
polega na tym, że ta ostatnia jawnie wykonuje przydział sterty. Należy jednak zauważyć, że jest to zależne od wdrożenia i dlatego może ulec zmianie.Porównywanie
make
z nienew
ma większego sensu, ponieważ te dwie funkcje pełnią zupełnie różne funkcje. Ale wyjaśniono to szczegółowo w powiązanym artykule.źródło
&T{}
jawnie wykonuje alokację sterty, jest AFAIK nieoparte na niczym w specyfikacji. Właściwie uważam, analiza ucieczka już utrzymanie takiego * t na stosie w miarę możliwości w dokładnie taki sam sposób jak znew(T)
.new (T): zwraca wskaźnik, aby wpisać T wartość typu * T, przydziela i zeruje pamięć. nowy (T) jest równoważny z & T {} .
make (T): zwraca zainicjowaną wartość typu T , przydziela i inicjuje pamięć. Jest używany do plasterków, mapy i kanałów.
źródło