Menu
Coddy logo textTech

Funkcja `init`

Część sekcji Logika i przepływ sterowania ścieżki GO w Coddy. Lekcja 56 z 68.

Funkcja init jest specjalną funkcją w Go, która uruchamia się automatycznie po zaimportowaniu pakietu. W przeciwieństwie do zwykłych funkcji nie wywołujesz bezpośrednio init — Go wykonuje ją za Ciebie podczas inicjalizacji pakietu.

Oto jak definiuje się funkcję init:

package mypackage

import "fmt"

func init() {
    fmt.Println("Package mypackage is being initialized!")
}

Funkcja init ma kilka wyjątkowych cech: nie przyjmuje parametrów, nie zwraca żadnych wartości i uruchamia się przed rozpoczęciem funkcji main. Dzięki temu doskonale nadaje się do ustawiania stanu początkowego, rejestrowania komponentów lub wykonywania jednorazowych zadań konfiguracyjnych wymaganych przez pakiet.

Gdy zaimportujesz pakiet zawierający funkcję init, od razu zobaczysz jej efekty, nawet jeśli nie użyjesz żadnej z eksportowanych funkcji tego pakietu. Dlatego poznany wcześniej wzorzec importu z pustym identyfikatorem jest tak przydatny — pozwala uruchomić inicjalizację pakietu bez bezpośredniego używania jego kodu.

challenge icon

Wyzwanie

Łatwy

Utwórz system inicjalizacji pakietów, który pokazuje, jak funkcje init wykonują się automatycznie podczas importowania pakietów. Zbudujesz system rejestrowania, w którym różne pakiety inicjalizują się samodzielnie i śledzą kolejność uruchamiania.

Otrzymasz dwa dane wejściowe:

  • Ciąg zawierający definicje pakietów w formacie "package1:message1,package2:message2,package3:message3" (np. "database:Database connection pool initialized,cache:Cache system ready,logger:Logging system started")
  • Ciąg zawierający operacje programu głównego w formacie "operation1,operation2,operation3" (np. "start_server,process_requests,shutdown")

Twoim zadaniem jest:

  1. Przeanalizować pierwsze dane wejściowe, dzieląc je po przecinkach, aby uzyskać poszczególne definicje pakietów
  2. Dla każdej definicji pakietu podzielić ją po dwukropkach, aby uzyskać nazwę pakietu i komunikat inicjalizacyjny
  3. Utworzyć globalny wycinek o nazwie initLog, aby śledzić komunikaty inicjalizacyjne
  4. Utworzyć funkcję o nazwie logInit, która przyjmuje nazwę pakietu i komunikat, a następnie dodaje sformatowany komunikat "[INIT] [package_name]: [message]" do wycinka initLog
  5. Zasymulować inicjalizację pakietów, wywołując logInit dla każdego pakietu w kolejności, w jakiej występuje w danych wejściowych
  6. Wyświetlić nagłówek sekwencji inicjalizacji: "=== PACKAGE INITIALIZATION SEQUENCE ==="
  7. Wypisać każdy komunikat inicjalizacyjny z wycinka initLog
  8. Wyświetlić nagłówek programu głównego: "=== MAIN PROGRAM EXECUTION ==="
  9. Wypisać: "All packages initialized successfully"
  10. Przeanalizować drugie dane wejściowe, dzieląc je po przecinkach, aby uzyskać poszczególne operacje
  11. Dla każdej operacji programu głównego:
    • Wypisać: "Executing: [operation]"
    • Dodać komunikat do dziennika: "[MAIN] Operation: [operation]"
  12. Wyświetlić podsumowanie wykonania:
    • "=== EXECUTION SUMMARY ==="
    • "Packages initialized: [number_of_packages]"
    • "Main operations executed: [number_of_operations]"
    • "Total log entries: [total_number_of_log_entries]"
  13. Wyświetlić pełny dziennik:
    • "=== COMPLETE EXECUTION LOG ==="
    • Wypisać każdy wpis z pełnego dziennika (zarówno komunikaty inicjalizacyjne, jak i operacje programu głównego)
  14. Wyświetlić końcowy komunikat: "Program execution completed - all init functions ran before main"

Użyj pakietu strings do dzielenia ciągów wejściowych oraz pakietu fmt do formatowanego wyjścia. To wyzwanie pokazuje, jak funkcje init wykonują się automatycznie podczas importowania pakietu i zawsze uruchamiają się przed funkcją main, dzięki czemu doskonale nadają się do konfiguracji i inicjalizacji pakietów.

Spróbuj swoich sił

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// Globalny wycinek do śledzenia komunikatów inicjalizacji
var initLog []string

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Wczytaj dane wejściowe (bufio poprawnie obsługuje wiersze zawierające spacje)
	packageDefs, _ := reader.ReadString('\n')
	packageDefs = strings.TrimRight(packageDefs, "\r\n")

	mainOps, _ := reader.ReadString('\n')
	mainOps = strings.TrimRight(mainOps, "\r\n")

	// TODO: Napisz swój kod poniżej
	// 1. Podziel packageDefs według "," na poszczególne wpisy pakietów
	// 2. Każdy wpis podziel według ":" (maksymalnie na 2 części), aby uzyskać packageName i message
	// 3. Utwórz funkcję logInit(packageName, message string), która dodaje
	//    "[INIT] [packageName]: message" do globalnego wycinka initLog
	// 4. Wyświetl nagłówek sekwencji inicjalizacji i wszystkie wpisy dziennika inicjalizacji
	// 5. Wyświetl nagłówek głównej fazy wykonywania i przetwórz każdą operację z mainOps
	//    - Wypisz "Executing: <op>" dla każdej operacji
	//    - Dodaj "[MAIN] Operation: <op>" do initLog
	// 6. Wyświetl podsumowanie wykonania (liczbę pakietów, liczbę operacji, łączną liczbę wpisów dziennika)
	// 7. Wyświetl pełny dziennik i końcowy komunikat o zakończeniu

}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Logika i przepływ sterowania

Poćwicz samodzielnie: Kompilator Go online