Funkcja make w Go jest używana wyłącznie do inicjalizacji obiektów typów: slice, map i channel. Przydziela ona odpowiednią strukturę danych i zwraca gotowy do użycia obiekt (nie wskaźnik!).
Przykłady:
s := make([]int, 5, 10) // slice o długości 5, pojemności 10 m := make(map[string]int) // pusty map ch := make(chan int, 2) // buforowany kanał na 2
Szczegóły:
slice parametry: długość (len) i (opcjonalnie) pojemność (cap).map i chan — tylko (opcjonalna) pojemność (początkowy rozmiar/bufor).make zwraca już zainicjalizowany obiekt, gotowy do użycia.make nie jest używana, inicjalizuje się je za pomocą literałów lub new (która zwraca wskaźnik na zero value).Porównanie z new:
new(T) zwraca *T, gdzie wszystkie pola są zerowe.make(T) zwraca T tylko dla trzech typów: slice, map, chan.Czy można uzyskać działający map przez new zamiast make?
m := new(map[string]int) (*m)["a"] = 1 // Co się stanie?
Wielu uważa, że to poprawne, ale wystąpi panic w czasie działania: assignment to entry in nil map. Ponieważ w zmiennej *m jest nil!
Poprawnie: używać make:
m := make(map[string]int) m["a"] = 1 // OK
Historia
W mikroserwisie do przechowywania pamięci podręcznej stworzono mapę przez var cache map[string]interface{} bez inicjalizacji make, co spowodowało panic przy zapisywaniu w produkcji z niezrozumiałymi stack trace. Problem został znaleziony dopiero po analizie kodu: mapa była nil.
Historia
Podczas pisania potoku danych zapomniano o buforze w kanale i stworzono przez make(chan int). W rezultacie, gorutyny utknęły, czekając na odczyt, chociaż oczekiwano asynchronicznej wymiany. Błąd zauważono dopiero podczas testów skalowania.
Historia
W projekcie, gdzie inicjalizacja odbywała się przez new, niektórzy programiści próbowali używać new([]int) zamiast make([]int, 10), w rezultacie otrzymali wskaźnik na nil slice i panic w czasie działania przy pierwszych próbach zapisu.