Pusty interfejs (any)
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 28 z 107.
Pusty interfejs to interfejs, który nie ma żadnych metod. Ponieważ każdy typ w Go ma co najmniej zero metod, każdy typ automatycznie spełnia warunki pustego interfejsu. Dzięki temu może przechowywać wartości dowolnego typu.
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}W Go 1.18 wprowadzono słowo kluczowe any jako alias dla interface{}. Są całkowicie wymienne, ale any jest czytelniejsze.
var value any = "Go is awesome"Pusty interfejs jest przydatny, gdy trzeba obsługiwać wartości o nieznanych lub zmiennych typach. Funkcje takie jak fmt.Println używają go, aby przyjmować argumenty dowolnego typu:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}Istnieje jednak pewien kompromis. Gdy wartość jest przechowywana w pustym interfejsie, tracisz dostęp do informacji o jej konkretnym typie.
Nie możesz bezpośrednio wywoływać metod ani uzyskiwać dostępu do pól bez wcześniejszego wyodrębnienia bazowego typu. W następnych lekcjach dowiesz się, jak pobrać konkretny typ z pustego interfejsu za pomocą asercji typów i przełączników typów.
Wyzwanie
ŁatwyZbudujmy elastyczny pojemnik do przechowywania, który może przechowywać wartości dowolnego typu za pomocą pustego interfejsu. Utworzysz proste pudełko, które pokazuje, jak any pozwala przechowywać różne typy w tej samej strukturze.
Rozmieścisz swój kod w dwóch plikach:
box.go: Zdefiniuj strukturęBoxz jednym polemContenttypuany. Utwórz funkcję konstruktoraNewBox, która przyjmuje wartość dowolnego typu i zwraca wskaźnik do obiektu Box zawierającego tę wartość. Dodaj metodęDescribe, która zwraca tekst opisujący, co jest przechowywane w pudełku.main.go: Odczytaj różne wartości z wejścia, utwórz pudełka zawierające liczbę całkowitą, tekst i wartość logiczną, a następnie wyświetl opis każdego pudełka, aby pokazać, jak ten sam typ Box może przechowywać zupełnie różne wartości.
Dane wejściowe będą następujące:
- Wiersz 1: Wartość całkowita
- Wiersz 2: Wartość tekstowa
- Wiersz 3: Wartość logiczna (
truelubfalse)
Metoda Describe powinna zwracać tekst w następującym formacie:
Box contains: [value]Na przykład dla wartości 42, hello i true wynik powinien wyglądać następująco:
Box contains: 42
Box contains: hello
Box contains: trueNajważniejszy wniosek jest taki, że pojedyncza struktura Box może przechowywać liczbę całkowitą, tekst lub wartość logiczną: wszystko dzięki temu, że typ any akceptuje wartości dowolnego typu. Każde pudełko przechowuje coś innego, a mimo to wszystkie są tego samego typu Box.
Spróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Wczytaj wartość całkowitą
line1, _ := reader.ReadString('\n')
intVal, _ := strconv.Atoi(strings.TrimSpace(line1))
// Wczytaj wartość tekstową
line2, _ := reader.ReadString('\n')
strVal := strings.TrimSpace(line2)
// Wczytaj wartość logiczną
line3, _ := reader.ReadString('\n')
boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))
// TODO: Utwórz pudełko dla każdej wartości za pomocą NewBox
// TODO: Wypisz opis każdego pudełka za pomocą metody Describe
// Użyj zmiennych, aby uniknąć błędów kompilacji (usuń te wiersze podczas implementacji)
_ = intVal
_ = strVal
_ = boolVal
// Przykładowy format wyjścia:
// fmt.Println(box.Describe())
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP w Go
Pliki zewnętrzneObszar roboczy i moduły GoPakiety i importyNazwy eksportowane i nieeksportowaneWprowadzenie do OOP w GoStruktury jako klasyDefiniowanie metod dla strukturOdbiorniki wskaźnikowe i wartościoweInicjalizacja strukturFunkcje konstruktoraPodsumowanie – prosty kalkulator4Interfejsy
Wprowadzenie do interfejsówImplementacja niejawnaInterfejs jako kontraktPusty interfejs (any)Asercja typuPrzełącznik typówKompozycja interfejsówInterfejsy Stringer i ErrorPowtórka — kalkulator figur7Hermetyzacja
Pola eksportowane i nieeksportowaneHermetyzacja na poziomie pakietuMetody pobierające i ustawiająceUkrywanie informacji w GoPowtórka – dane studentów10Typy generyczne (Go 1.18+)
Wprowadzenie do typów generycznychParametry typówOgraniczenia typówStruktury generyczneObejście ograniczeń metod generycznychPodsumowanie — generyczna kolekcja2Typy i struktury w praktyce
Typy proste i złożoneDefiniowanie własnych typówTagi pól strukturStruktury anonimoweStruktury zagnieżdżoneWartości zerowe i domyślnePodsumowanie – książka kontaktów5Kompozycja zamiast dziedziczenia
Dlaczego Go nie ma dziedziczeniaPodstawy osadzania strukturPromowanie metodOsadzanie wielu strukturOsadzanie a agregacjaPrzesłanianie osadzonych metodPodsumowanie — hierarchia pracowników8Obsługa błędów i programowanie obiektowe
Interfejs błęduWłasne typy błędówOpakowywanie błędów (fmt.Errorf)Błędy wartowniczeerrors.Is() i errors.As()Panic, Defer i RecoverPodsumowanie — parser plików3Wskaźniki i pamięć
Podstawy wskaźników w GoWskaźniki do strukturPrzekazywanie przez wartość a przez referencjęFunkcja new()Odśmiecanie pamięci w GoPowtórka — kreator listy wiązanej6Polimorfizm w Go
Polimorfizm za pomocą interfejsówDuck typing w GoZasady spełniania interfejsówKolekcje polimorficzneWstrzykiwanie zależnościPowtórka — procesor płatności9Współbieżność i OOP
Podstawy goroutinesKanały i komunikacjaKanały buforowane i niebuforowaneInstrukcja selectsync.Mutex i sync.RWMutexsync.WaitGroupProjektowanie struktur bezpiecznych wątkowoPowtórka – pula workerów12Zaawansowane zagadnienia programowania obiektowego
Wzorzec opcji funkcyjnychWzorzec Builder w GoŁańcuchowe wywoływanie metodAliasy typów a definicje typówPodstawy refleksjiPrzegląd generowania koduPoćwicz samodzielnie: Kompilator Go online