Kompozycja interfejsów i dobre praktyki
Małe interfejsy i odwrócenie zależności
Kompozycja interfejsów i dobre praktyki to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.
Kompozycja interfejsów
Interfejsy Go mogą osadzać inne interfejsy, aby tworzyć większe interfejsy:
package main
import "io"
// io.ReadWriter composes Reader and Writer
type ReadWriter interface {
io.Reader
io.Writer
}
// Your own composition:
type Processor interface {
io.Reader
Process() error
io.Closer
}
func main() { _ = (*Processor)(nil) }Zasada małych interfejsów
Najbardziej użyteczne interfejsy Go mają jedną lub dwie metody. Maksymalizuje to liczbę typów, które mogą je implementować:
io.Reader— 1 metodaio.Writer— 1 metodaerror— 1 metodafmt.Stringer— 1 metoda
Duże interfejsy są trudniejsze do mockowania i testowania.
Odwrócenie zależności
Przyjmuj interfejsy w parametrach funkcji zamiast typów konkretnych. Dzięki temu kod nie jest zależny od konkretnych implementacji:
package main
import "fmt"
type Store interface {
Get(key string) (string, bool)
Set(key, val string)
}
func cache(s Store, key, value string) {
if _, ok := s.Get(key); !ok {
s.Set(key, value)
}
}
type MapStore struct{ m map[string]string }
func (ms *MapStore) Get(k string) (string, bool) { v, ok := ms.m[k]; return v, ok }
func (ms *MapStore) Set(k, v string) { ms.m[k] = v }
func main() {
s := &MapStore{m: map[string]string{}}
cache(s, "x", "hello")
v, _ := s.Get("x")
fmt.Println(v)
}Segregacja interfejsów
Podziel duże interfejsy na mniejsze i ukierunkowane. Kod korzystający z interfejsu zależy tylko od używanych metod:
package main
// Bad: large interface forces all methods
type BigStorage interface {
Read(key string) string
Write(key, val string)
Delete(key string)
List() []string
Backup() error
}
// Good: small, focused interfaces
type Reader interface{ Read(key string) string }
type Writer interface{ Write(key, val string) }
type Lister interface{ List() []string }
func readAll(r Reader) {} // only needs Read
func main() { _ = readAll }Zwracanie typów konkretnych
Konstruktory powinny zwracać typy konkretne, a nie interfejsy. Kod wywołujący zawsze może przypisać typ konkretny do zmiennej interfejsowej:
package main
type Logger interface{ Log(string) }
type ConsoleLogger struct{}
func (c *ConsoleLogger) Log(s string) {}
// Good: return concrete *ConsoleLogger
func NewConsoleLogger() *ConsoleLogger { return &ConsoleLogger{} }
// Avoid: return Logger (hides the concrete type)
// func NewConsoleLogger() Logger { return &ConsoleLogger{} }
func main() { _ = NewConsoleLogger() }Nadmiar interfejsów
Nie twórz interfejsu dla każdego typu „na wszelki wypadek”. Twórz interfejsy tylko wtedy, gdy:
- Masz już lub wkrótce będziesz mieć wiele implementacji
- Potrzebujesz mockować zależność w testach
- Tworzysz bibliotekę i chcesz oddzielić kod wywołujący od implementacji
Osadzanie interfejsów w celu rozszerzania
Osadź interfejs, aby dodać opcjonalne metody z implementacjami domyślnymi:
package main
import "fmt"
type Handler interface{ Handle(msg string) }
type NamedHandler interface {
Handler
Name() string
}
func dispatch(h Handler) {
if nh, ok := h.(NamedHandler); ok {
fmt.Printf("[%s] ", nh.Name())
}
h.Handle("event")
}
type MyHandler struct{}
func (m MyHandler) Handle(msg string) { fmt.Println(msg) }
func (m MyHandler) Name() string { return "my" }
func main() { dispatch(MyHandler{}) }Mockowanie za pomocą interfejsów
Zdefiniuj zależności jako interfejsy; w testach wstrzykuj mocki:
package main
import "fmt"
type Clock interface{ Now() int64 }
type MockClock struct{ T int64 }
func (m MockClock) Now() int64 { return m.T }
func isExpired(c Clock, expiresAt int64) bool {
return c.Now() > expiresAt
}
func main() {
mc := MockClock{T: 1000}
fmt.Println(isExpired(mc, 500)) // true
fmt.Println(isExpired(mc, 1500)) // false
}Osadzanie interfejsów a struktur w celu ponownego użycia
Używaj osadzania interfejsów do komponowania API, a osadzania struktur do ponownego użycia kodu. Służą różnym celom i nie należy ich mylić.
Sprawdzanie zgodności z interfejsem w czasie kompilacji
Użyj sprawdzenia kompilacyjnego z pustym identyfikatorem, aby zweryfikować, czy typ spełnia wymagania interfejsu:
package main
type Doer interface{ Do() }
type MyType struct{}
func (m *MyType) Do() {}
// Compile-time check — no runtime cost
var _ Doer = (*MyType)(nil)
func main() {}Szybkie sprawdzenie
Kiedy należy definiować nowy interfejs w Go?
Podsumowanie: dobre praktyki dotyczące interfejsów
Najważniejsze informacje:
- Utrzymuj małe interfejsy — jedna lub dwie metody
- Komponuj interfejsy z mniejszych interfejsów
- Przyjmuj interfejsy, zwracaj typy konkretne
- Twórz interfejsy na potrzeby testowalności i wielu implementacji
- Używaj sprawdzenia kompilacyjnego z przypisaniem do pustego identyfikatora
Zadanie praktyczne
Zaprojektuj interfejs Notifier z metodą Notify(msg string) error. Zaimplementuj go dla typów EmailNotifier i SMSNotifier. Napisz funkcję broadcast, która wysyła powiadomienia do elementów []Notifier.
Ucz się Go dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 51
- Lekcje
- 203
Często zadawane pytania
Czy lekcja „Kompozycja interfejsów i dobre praktyki” jest bezpłatna?
Tak — pełny tekst „Kompozycja interfejsów i dobre praktyki” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Kompozycja interfejsów i dobre praktyki”?
Małe interfejsy i odwrócenie zależności Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Go Academy?
Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Kompozycja interfejsów i dobre praktyki”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?
Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Definiowanie i implementowanie interfejsów
- Podstawowe interfejsy biblioteki standardowej
- Asercje typów i przełączniki typów
- Kompozycja interfejsów i dobre praktyki