Ви можете посилатися на статтю " Як використовувати інтерфейси в Go " (на основі " опису інтерфейсів Russ Cox "):
Що таке інтерфейс?
Інтерфейс - це дві речі:
- це набір методів,
- але це також тип
interface{}Типу, порожній інтерфейс є інтерфейсом , який не має методів.
Оскільки не існує ключового слова реалізації, всі типи реалізують принаймні нульові методи, а задоволення інтерфейсу здійснюється автоматично, усі типи задовольняють порожній інтерфейс .
Це означає, що якщо ви пишете функцію, яка приймає interface{}значення як параметр, ви можете надати цій функції будь-яке значення .
(Це те, що Msgвідображається у вашому запитанні: будь-яке значення)
func DoSomething(v interface{}) {
// ...
}
Ось де це стає заплутаним:
Всередині DoSomethingфункції, що таке vтип?
Початківські ховрахи примушують вважати, що " vє будь-якого типу", але це неправильно.
vне має будь-якого типу; це interface{}типу .
Передаючи значення у DoSomethingфункцію, час виконання Go виконає перетворення типу (якщо це необхідно) та перетворить значення у interface{}значення .
Усі значення мають рівно один тип під час виконання, а vодин - статичний тип interface{}.
Значення інтерфейсу складається з двох слів даних :
- одне слово використовується для вказівки на таблицю методів для базового типу значення,
- а інше слово використовується для вказівки на фактичні дані, що зберігаються цим значенням.
Додаток: Це стаття Русса досить повна щодо структури інтерфейсу:
type Stringer interface {
String() string
}
Значення інтерфейсу представлені у вигляді пари двох слів, що дає вказівник на інформацію про тип, що зберігається в інтерфейсі, та вказівник на пов’язані дані.
Призначення b до значення інтерфейсу типу Stringer встановлює обидва слова значення інтерфейсу.

Перше слово в значенні інтерфейсу вказує на те, що я називаю таблицю інтерфейсу або itable (вимовляється i-table; у джерелах виконання час ім'я реалізації C - це Itab).
Itable починається з деяких метаданих про задіяні типи, а потім стає списком функціональних покажчиків.
Зауважте, що itable відповідає типу інтерфейсу, а не динамічному типу .
З точки зору нашого прикладу, itable для Stringerпроведення типу Binary перелічує методи, які використовуються для задоволення Stringer, а це просто String: інші методи Binary ( Get) не відображають у itable.
Друге слово у значенні інтерфейсу вказує на фактичні дані , в даному випадку - копію b.
Призначення var s Stringer = bробить копію, bа не точку на bтій же причині, що var c uint64 = bі копію: якщо bпізніші зміни sі cповинні мати початкове значення, а не нове.
Значення, що зберігаються в інтерфейсах, можуть бути довільно великими, але лише одне слово присвячене утриманню значення в структурі інтерфейсу, тому присвоєння виділяє шматок пам’яті на купі і записує вказівник в однослове слот.
interface{}є більш-менш еквівалентомvoid *у C. Це може вказувати на що завгодно, і для його використання потрібне твердження лиття / типу.