0Pricing
Go Academy · Lekcja

Dynamiczne wywołania funkcji

Wywoływanie funkcji i ustawianie wartości za pomocą reflect

Dynamiczne wywołania funkcji to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 3 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.

reflect.Value.Call

Value.Call(args) wywołuje funkcję reprezentowaną przez Value z podanymi argumentami (jako []reflect.Value) i zwraca wyniki jako []reflect.Value.

fn := reflect.ValueOf(add)
results := fn.Call([]reflect.Value{
    reflect.ValueOf(2),
    reflect.ValueOf(3),
})
fmt.Println(results[0].Int()) // 5

Sprawdzanie typów argumentów

Przed wywołaniem należy upewnić się, że typy argumentów są zgodne z sygnaturą funkcji. Niezgodne typy powodują panikę.

t := reflect.TypeOf(fn)
if t.NumIn() != len(args) { panic("wrong arg count") }
for i, arg := range args {
    if !reflect.TypeOf(arg).AssignableTo(t.In(i)) { panic("type mismatch") }
}

Funkcje wariadyczne

Funkcję wariadyczną można wywołać za pomocą Value.Call (rozwijając slice) lub Value.CallSlice (przekazując argumenty wariadyczne jako wartość typu slice):

sum := reflect.ValueOf(func(ns ...int) int {
    total := 0
    for _, n := range ns { total += n }
    return total
})
args := reflect.ValueOf([]int{1,2,3})
results := sum.CallSlice([]reflect.Value{args})

reflect.MakeFunc

reflect.MakeFunc tworzy nową funkcję w czasie działania na podstawie określonego typu i treści wrappera. Służy do generowania funkcji-adapterów dla interfejsów.

t := reflect.TypeOf(func(int) string { return "" })
fn := reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value {
    return []reflect.Value{reflect.ValueOf(strconv.Itoa(args[0].Interface().(int)))}
})

Wywoływanie metod po nazwie

Pobrać metodę po nazwie i ją wywołać:

v := reflect.ValueOf(myObj)
m := v.MethodByName("Process")
if m.IsValid() {
    m.Call(nil)
}

Sprawdzanie, czy metoda istnieje

Zawsze należy sprawdzać m.IsValid() przed wywołaniem — MethodByName zwraca wartość zerową, jeśli metoda nie zostanie znaleziona, a wywołanie wartości zerowej powoduje panikę.

Zastosowania dynamicznego wywoływania

Dynamiczne wywołania funkcji są używane w systemach wtyczek (wywoływanie funkcji na podstawie nazw), frameworkach testowych (wywoływanie funkcji TestXxx), dispatcherach RPC (mapowanie nazw metod na handlery) oraz dekoratorach.

Wydajność

reflect.Call jest około 10-50× wolniejsze od bezpośredniego wywołania. Należy buforować reflect.Value często wywoływanych funkcji i unikać ich używania w gorących pętlach.

Wrapper z kontrolą typów

Należy opakować dynamiczne wywołania w pomocniczą funkcję o określonych typach, która wykonuje operacje refleksyjne raz podczas uruchamiania i wielokrotnie wywołuje zbuforowaną wartość:

type Processor func(context.Context, []byte) ([]byte, error)
// Build at startup, reuse at request time

Obsługa zwracania błędów

Jeśli funkcja zwraca błąd jako ostatni wynik, należy go wyodrębnić i sprawdzić:

results := fn.Call(args)
if !results[len(results)-1].IsNil() {
    return results[len(results)-1].Interface().(error)
}

Alternatywy dla refleksji

Jeśli zbiór funkcji jest znany w czasie kompilacji, zamiast refleksji należy użyć mapy wartości funkcji (map[string]func(...)) — jest to bezpieczniejsze i szybsze.

handlers := map[string]func(ctx context.Context, req []byte) []byte{
    "greet": greetHandler,
}

Szybkie sprawdzenie

Co zwraca reflect.Value.Call?

Podsumowanie: dynamiczne wywołania funkcji

Najważniejsze informacje:

  • Value.Call([]reflect.Value) wywołuje funkcję; zwraca []reflect.Value
  • Przed wywołaniem wyniku MethodByName należy sprawdzić m.IsValid()
  • MakeFunc tworzy nową funkcję określonego typu w czasie działania
  • W przypadku znanych zbiorów funkcji preferować map[string]func zamiast refleksji

Często zadawane pytania

Czy lekcja „Dynamiczne wywołania funkcji” jest bezpłatna?

Tak — pełny tekst „Dynamiczne wywołania funkcji” 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 „Dynamiczne wywołania funkcji”?

Wywoływanie funkcji i ustawianie wartości za pomocą reflect Ć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 3 z 4.

Ile czasu zajmuje lekcja „Dynamiczne wywołania funkcji”?

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

  1. reflect.Type i reflect.Value
  2. Inspekcja pól i tagów struktur
  3. Dynamiczne wywołania funkcji
  4. Refleksja w praktyce: serializatory
← Powrót do Go Academy