В трекере Go обсуждают предложение #47487. Оно разрешает приводить значение функции к интерфейсу с ровно одним методом, если сигнатура функции совпадает с сигнатурой этого метода. На момент обсуждения предложение помечено как likely accept. Это значит, что склонны принять, но сначала хотят прототип и эксперименты.
Сейчас, чтобы замыкание реализовало интерфейс, приходится заводить отдельный тип с методом.
Классический пример из стандартной библиотеки это
http.HandlerFunc. Шаблон выглядит так:type FooerFunc func(A, B) (C, D)
func (f FooerFunc) Foo(a A, b B) (C, D) {
return f(a, b)
}
Когда нужен, например,
io.Writer, который считает записанные байты, обычно пишут структуру с полем и методом Write. Кода становится больше, чем сути, а единственная важная строка теряется среди обвязки.Что предлагают
Предложение даёт писать то же самое через приведение функции к интерфейсу напрямую:
var N int64
cw := io.Writer(func(p []byte) (n int, err error) {
n, err = os.Stdout.Write(p)
N += int64(n)
return n, err
})
Важная деталь в том, что это именно явное приведение, а не неявное присваивание. У
io.Reader и io.Writer одинаковая сигнатура метода, поэтому неявное превращение было бы опасным. Явное приведение снимает двусмысленность, ведь вы сами указываете, чем должна стать функция.По задумке компилятор сам сгенерирует скрытый именованный тип с неэкспортируемым именем, который и несёт метод. Менять
reflect, инструменты или работу с type assertion при этом не нужно. Более того, функцию можно положить прямо в таблицу методов, и тогда лишних накладных расходов на обёртку не будет.Альтернатива
В обсуждении всплыл и более общий вариант. Это интерфейсные литералы из #25860, где интерфейс собирают из нескольких замыканий, по одному на каждый метод:
cw := io.Writer{
Write: func(p []byte) (n int, err error) {
// ...
},
}Такой вариант не ограничен одним методом, но его заметно сложнее встроить в текущий язык.
Часть участников переживает, что появится ещё один способ писать одно и то же, и это размывает консистентность Go, за которую язык и ценят. Решение пока не финальное. Если предложение примут, обвязочных типов вроде
http.HandlerFunc в коде станет заметно меньше.📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max
🐸 Библиотека Go-разработчика
#GoLive