Самопроизвольное приведение типа... Разрушение структуры... Или чёрт знает как это назвать

67 views
Skip to first unread message

Александр Рем

unread,
Jul 9, 2019, 11:10:29 AM7/9/19
to Golang Russian
Доброго времени, уважаемые.

Даже не знаю как толком описать непонятное мне поведение, по этому накидал пример:

Попробую пояснить на словах:
Предположим для целого спектра структур есть ряд идентичных методов.
Выношу их в некую структуру Simple.
Встраиваю её во все другие нужные мне структуры, назовём Extended.
Объявляю интерфейс SimpleIntrf, которому удовлетворяет и Extended.
Вроде бы получил, что хотел...

Но почему-то при использовании методов Simple на структурах Extended, в некоторых, не во всех случаях тип структуры Extended превращается в Simple и структура теряет поля относящиеся к Extended.
Так в примере это метод SetParentNode()
При этом например добавленные в поле Childs структуры Extended остаются в первозданной красоте.
Не врубаюсь в чём дело.
Разница только в том, что поле Parent SimpleIntrf а поле  Childs []SimpleIntrf

Andrey Velikoredchanin

unread,
Jul 9, 2019, 11:57:57 AM7/9/19
to golang-ru
Это правильное поведение. Методы, привязанные к Simple могут оперировать только полями общими для Simple и Extended. И это логично. Что-бы было по другому, соответствующий метод надо ОТДЕЛЬНО реализовать для Extended.

вт, 9 июл. 2019 г. в 18:10, Александр Рем <gen...@live.ru>:
--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/golang-ru/425d21d9-7fb3-4434-b1f2-624a6de64462%40googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Александр Рем

unread,
Jul 9, 2019, 11:59:22 AM7/9/19
to Golang Russian

Как-то совсем странно...
Не вижу в чём загвоздка.

я переписал поле Parent  теперь оно идентично Childs

type Simple struct {
    Parent []SimpleIntrf
    Childs []SimpleIntrf
}

Но на выходе всё равно
fmt.Printf("%T", child.Parent[0])  ------> *main.Simple
а
fmt.Printf("%T", parent.Childs[0]) -------> *main.Extended

Александр Рем

unread,
Jul 9, 2019, 12:05:37 PM7/9/19
to Golang Russian
ну Extended удовлетворяет интерфейсу SimpleIntrf и я не пытаюсь задействовать какие либо другие методы.
Мне непонятно где "косяк", почему опрос типа в одном случае даёт мне Extended, а в другом Simple?

Чуть ниже я написал что сделал поля Parent  и Childs идентичными

type Simple struct {
    Parent []SimpleIntrf
    Childs []SimpleIntrf
}

но вывод всё равно остался разным.

https://play.golang.org/p/-9V9wbC8x3w

Где то очевидная ошибка


вторник, 9 июля 2019 г., 18:57:57 UTC+3 пользователь Andrey Velikoredchanin написал:
Это правильное поведение. Методы, привязанные к Simple могут оперировать только полями общими для Simple и Extended. И это логично. Что-бы было по другому, соответствующий метод надо ОТДЕЛЬНО реализовать для Extended.

вт, 9 июл. 2019 г. в 18:10, Александр Рем <gen...@live.ru>:
Доброго времени, уважаемые.

Даже не знаю как толком описать непонятное мне поведение, по этому накидал пример:

Попробую пояснить на словах:
Предположим для целого спектра структур есть ряд идентичных методов.
Выношу их в некую структуру Simple.
Встраиваю её во все другие нужные мне структуры, назовём Extended.
Объявляю интерфейс SimpleIntrf, которому удовлетворяет и Extended.
Вроде бы получил, что хотел...

Но почему-то при использовании методов Simple на структурах Extended, в некоторых, не во всех случаях тип структуры Extended превращается в Simple и структура теряет поля относящиеся к Extended.
Так в примере это метод SetParentNode()
При этом например добавленные в поле Childs структуры Extended остаются в первозданной красоте.
Не врубаюсь в чём дело.
Разница только в том, что поле Parent SimpleIntrf а поле  Childs []SimpleIntrf

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес gola...@googlegroups.com.

Александр Рем

unread,
Jul 10, 2019, 2:49:29 PM7/10/19
to Golang Russian
Мда...............................

А если описать это всё отдельно (последовательно), через внешнюю функцию, то всё работает...
https://play.golang.org/p/fVaAjC_qAuV

А почему?....
Что изменилось?...

Oleg Bulatov

unread,
Jul 10, 2019, 3:03:16 PM7/10/19
to Golang Russian
func (parent *Simple) Add(child SimpleIntrf) {
parent.Childs = append(parent.Childs, child) 
child.SetParentNode(parent)
}

Здесь в SetParentNode передается объект типа Simple. То, что этот объект вложен в какой-то другой объект (Extended), данный код не знает и не учитывает.

Александр Рем

unread,
Jul 10, 2019, 11:45:04 PM7/10/19
to Golang Russian
Мда.., мда...
Не ожидал я такого...
Я конечно уже понимаю, что напр. интерфейсы введены как костыль, что бы обойти строгую типизацию, но что и встраивание структур не более чем костыль для удовлетворения интерфейсам?.. Мда...

Как же тогда всё это внятно использовать? Понимаю, что ни черта не понимаю )
Может кто нибудь посоветовать толковый материал, что нибудь типа "10 лучших практик" и т.п. где бы как-то было изложено не как написать пару огрызочных функций, а как Го использовать в бою на б.м. крупном материале?

А  то неясно как подходить ко всему этому... писать некие внешние к методам, типа функции вызывающие их у структур обёрнутых в интерфейс? как я сделал в последнем эксперименте или как?
//С манерой записи методов Го и интерфейсов листинг и так похож на какие то рваные ошмётки, а тут ещё добавлять... С ужасом думаю как потом читать сколько ниб крупный проект даже через пол года )

среда, 10 июля 2019 г., 22:03:16 UTC+3 пользователь Oleg Bulatov написал:

Oleg Bulatov

unread,
Jul 11, 2019, 3:45:24 AM7/11/19
to Golang Russian
Я бы не стал относиться к интерфейсам как к "костылю". Просто другой подход, отличный от классического ООП.

В Go нет иерархии типов, вся модель типов плоская. И если хочется иметь несколько типов (Simple, Extended) и какой-то общий для них код, то этот код делается в виде отдельной функции. Если он будет методом одного из типов, то он не сможет работать с другими типами.

И интерфейсы нужны как раз для возможности обобщать, некий аналог утиной типизации.

type Утка interface {
    Крякнуть()
}

Про крупные проекты: да, в Go нет кучи возможностей из других языков (неявный вызов деструкторов, наследование, возможность частично переопределить функции базового класса и заставить старые функции неявно использовать новый код, тьюринг-полные макросы, переопределение операторов и возможность получить от них исключение, и т.п.), но смотря на Kubernetes я очень этому рад. Перейдя в любое место программы можно хотя бы понять какой код задействован и как он будет выполняться.

Из толковых материалов: код. Go это не про красивую теорию, Go это про решение проблем.

Александр Рем

unread,
Jul 11, 2019, 3:55:35 AM7/11/19
to Golang Russian
Ясно, спасибо за пояснение
Авось как нибудь одолею)
(в принципе да, если не заморачиваться "красиво/не красиво", "избыточно/лаконично", то можно понавертеть чего-то, что даже работать будет)

четверг, 11 июля 2019 г., 10:45:24 UTC+3 пользователь Oleg Bulatov написал:

Александр Рем

unread,
Jul 11, 2019, 4:20:38 PM7/11/19
to Golang Russian
ОФФТоп...
Но я всётаки отнёс бы интерфейсы в Го к костылям :)

согласитесь - они ничего не делают, кроме как обходят строгую типизацию ;)

я бы напр., если бы проектировал ЯП, сделал интерфейсы больше "прокси" ...
И методы тогда бы не в структурах определял (оставил бы их тупо данными), а именно в интерфейсе...
//избежали бы многих дурацких вещей... в том числе полурабочего встраивания структур..
Эх.. ну да кто я.. )

четверг, 11 июля 2019 г., 10:55:35 UTC+3 пользователь Александр Рем написал:

Daniel Podolsky

unread,
Jul 11, 2019, 4:58:10 PM7/11/19
to gola...@googlegroups.com
> Но я всётаки отнёс бы интерфейсы в Го к костылям :)

если быть go-разработчиком - не выгодно к ним так относиться.

> согласитесь - они ничего не делают, кроме как обходят строгую типизацию ;)

нет, не обходят.

они предоставляют нам удачный доступ к полиморфизму без опасности
расшаривания данных (в go очень многое сделано для того, чтобы not
communicate by sharing memory; instead, share memory by communicating
сделать проще, а противоположное - сложнее)

> Эх.. ну да кто я.. )

автор несколькох промышленных языков? нет?!
Reply all
Reply to author
Forward
0 new messages