Ответ 1
Он терпит неудачу, потому что подписи не совпадают.
Когда вы вызываете Println(3)
, функция не принимает целое число в качестве своего первого аргумента. Скорее целое число упаковывается внутри переменной interface{}
(автоматическое преобразование, поскольку целые числа соответствуют интерфейсу), и эта переменная передается функции. Это преобразование происходит на вызывающей стороне, поэтому процесс вызова функции отличается от вызова функции, соответствующей func(i int)
.
Если вы хотите написать функцию, которая принимает произвольные унарные функции, вам нужно будет объявить ее в качестве аргумента переменной interface{}
, а затем проверить значение с помощью пакета reflect
. Пакет reflect
также может помочь вам вызвать произвольные функции, когда вы не знаете подпись во время компиляции.
Например:
func Map(f, v interface{}) interface{} {
fn := reflect.ValueOf(f)
fnType := fn.Type()
if fnType.Kind() != reflect.Func || fnType.NumIn() != 1 || fnType.NumOut() != 1 {
panic("Expected a unary function returning a single value")
}
res := fn.Call([]reflect.Value{reflect.ValueOf(v)})
return res[0].Interface()
}
Это вызовет данную функцию f
с аргументом v
и вернет результат. Если v
присваивается первому аргументу f
, вызов будет успешным без паники. Вы можете поэкспериментировать с этим примером здесь: http://play.golang.org/p/kkBu56JYb8