programowanieProgramista Backend

Wyjaśnij, jak działa typowanie i sprawdzanie typów w Go. Jakie rodzaje konwersji typów istnieją i czym się różnią?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W języku Go zastosowano statyczne ścisłe typowanie. Oznacza to, że typ każdej zmiennej jest znany w czasie kompilacji, a kompilator nie pozwala na wykonywanie operacji z niekompatybilnymi typami.

Istnieją dwa rodzaje konwersji typów:

  1. Jawna konwersja typów (Type Casting) – gdy programista wyraźnie wskazuje pożądany typ.
  2. Assertion (type assertion) – stosowane dla interfejsów w celu sprawdzenia konkretnego podległego typu.

Przykład jawnej konwersji:

var i int = 42 var f float64 = float64(i)

Przykład type assertion:

var i interface{} = "hello" s, ok := i.(string) if ok { fmt.Println("Wartość string:", s) } else { fmt.Println("i nie jest stringiem") }

Konwersja jest możliwa tylko między kompatybilnymi typami bazowymi (int → float64, rune → int32, ale string → int — nie jest możliwe).

Pytanie z podstępem

Czy interface{} może przechowywać wartość nil i jak poprawnie sprawdzić, czy zmienna typu interfejs rzeczywiście jest nil?

Zwykła pułapka — porównywanie interfejsu zawierającego wartość nil z nil bezpośrednio:

var err error = nil var i interface{} = err fmt.Println(i == nil) // Oczekiwano true, ale będzie false!

Poprawny sposób:

Sprawdzenie, czy zarówno sam interfejs jest nil, jak i wewnętrzna wartość jest nil:

if i == nil || reflect.ValueOf(i).IsNil() { fmt.Println("i rzeczywiście jest nil") }

Przykłady rzeczywistych błędów z powodu braku znajomości niuansów tematu


Historia

W projekcie backendu programista próbował obsługiwać różne błędy przez interface{}, porównywał je z nil. W wyniku tego, błąd nie był poprawnie wykrywany — pojawiały się ukryte błędy i błędna logika zwracania błędów do klienta.


Historia

Migracja między float64 a int bez jawnego castu powodowała silent data loss: wartości były zaokrąglane lub przekazywane niepoprawnie, ponieważ kompilator Go wymaga jawnej konwersji dla podobnych operacji.


Historia

Podczas deserializacji wartości interfejsowych przy pracy z map[string]interface{} (np. z JSON) niespodziewane typy liczb (float64) prowadziły do paniki przy używaniu type assertion bez dodatkowej kontroli ok — serwis zawieszał się z powodu błędu w czasie wykonywania.