Pull to refresh

Comments 5

А случайно переменные в Go, т.е. тот же man, не состоят ли из ссылки на класс плюс ссылки на данные инстанса? Этого могло бы хватить для описания всех проблем с интерфейсами. Потому что тогда если переменная типа класс, на нил проверяется только data, а если interface, то и класс и данные. (Что по мне нелогично, что толку, что переменной интерфейса присвоен типизированный nil?)

В Go не существует классов. Мы можем создать методы не только для структур, но и для любого типа, производного от примитивного: хоть от bool, хоть от int. Соответственно, любой созданный нами тип может реализовывать любой интерфейс. А абсолютно все типы (включая изначально встроенные в язык) реализуют интерфейс interface{}.

Особенностью принятого в Go подхода является то, что мы можем совершенно корректно вызвать метод для типизированного nullable-указателя. Так что поведение интерфейса, равного nil, и интерфейса, содержащего указатель на nil, отличается не только при сравнении с nil, но и при вызове методов этого интерфейса.

Ссылку на тип содержат только переменные-интерфейсы. Все прочие переменные имеют тип, точно известный в момент компиляции, и компилятор просто подставляет информацию о типе в нужные места кода.

Го типизированный язык, данными структур и других атомарных типов компилятор может дирижировать как ему угодно, что позволяет не хранить в рантайме для них информацию о типе. Эта информация вкладывается в контейнер интерфейса при присваивании значения только во время компиляции.

Для слайсов, мап, каналов, интерфейсов оператор '==' работает над контейнером, а не над данными внутри.
Нетипизированный nil присваивается в контейнер, а типизированный в данные контейнера.
Чтобы узнать что в данных значение nil нужно преобразовать интерфейс сначала в этот тип, затем проверить на nil, либо через рефлексию получить сырой указатель и уже работать с ним.
Пример: https://go.dev/play/p/LHO6WsI9hY_R

Sign up to leave a comment.

Articles