Ответ 1
Поля вашего анонимного типа структуры не экспортируются. Это означает, что вы не можете создавать значения этой структуры и указывать значения для полей из другого пакета. Spec: Композитные литералы:
Это ошибка для указания элемента для неэкпортируемого поля структуры, принадлежащей другому пакету.
Если вы измените определение структуры для экспорта полей, оно будет работать, потому что все поля могут быть назначены другими пакетами (см. Siu Ching Pong -Asuka Kenji- answer).
Это также относится к пустой структуре (без полей): пустая структура не имеет полей, поэтому она не имеет невыполненных полей, поэтому вам разрешено передать ее значение.
Вы можете вызвать функцию с немодифицированной структурой (с невыполненными полями) через отражение. Вы можете получить reflect.Type
функции PrintAnonymous()
, и вы можете использовать Type.In()
, чтобы получить reflect.Type
своего первого параметр. Это анонимная структура, для которой мы хотим передать значение. И вы можете построить значение этого типа, используя reflect.New()
. Это будет reflect.Value
, заверяющий указатель на zero значение анонимной структуры. К сожалению, вы не можете иметь значение struct с полями, отличными от нуля (по причине, упомянутой выше).
Вот как это могло бы выглядеть:
v := reflect.ValueOf(somepackage.PrintAnonymous)
paramt := v.Type().In(0)
v.Call([]reflect.Value{reflect.New(paramt).Elem()})
Это напечатает:
0:
0
- это нулевое значение для int
и ""
пустая строка для string
.
Для более глубокого проникновения внутрь системы типов и структур с невыдвинутыми полями см. связанные вопросы:
Идентифицировать не встроенные типы, используя отражение
Как клонировать структуру с нераспределенным полем?
Интересно (это ошибка, см. связанную проблему ниже), используя рефлексию, вы можете использовать значение своего собственного типа анонимной структуры (с сопоставленными, непортированными полями), и в этом случае мы можем использовать значения, отличные от нуля значение полей структуры:
value := struct {
i int
s string
}{
1, "Hello, world!",
}
v.Call([]reflect.Value{reflect.ValueOf(value)})
Навыки (без паники):
1: Hello, world!
Причина, по которой это разрешено, связана с ошибкой в компиляторе. См. Примерный код ниже:
s := struct{ i int }{2}
t := reflect.TypeOf(s)
fmt.Printf("Name: %q, PkgPath: %q\n", t.Name(), t.PkgPath())
fmt.Printf("Name: %q, PkgPath: %q\n", t.Field(0).Name, t.Field(0).PkgPath)
t2 := reflect.TypeOf(subplay.PrintAnonymous).In(0)
fmt.Printf("Name: %q, PkgPath: %q\n", t2.Name(), t2.PkgPath())
fmt.Printf("Name: %q, PkgPath: %q\n", t2.Field(0).Name, t2.Field(0).PkgPath)
Выход:
Name: "", PkgPath: ""
Name: "i", PkgPath: "main"
Name: "", PkgPath: ""
Name: "i", PkgPath: "main"
Как вы можете увидеть непортированное поле i
как в анонимных типах структуры (в пакете main
, так и в somepackage
в качестве параметра функции PrintAnonymous()
)), - сообщите об этом же пакете, и, следовательно, их тип будет быть равно:
fmt.Println(t == t2) // Prints true
Примечание. Я считаю это недостатком: если это разрешено с помощью отражения, тогда это должно быть возможно без использования отражения. Если без отражения ошибка времени компиляции оправдана, то использование отражения должно привести к панике во время выполнения. Я открыл для этого проблему, вы можете следить за ней здесь: issue # 16616. Исправление в настоящее время нацелено на Go 1.8.