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:
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).
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") }
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.