Во втором варианте вроде как
так. Чтобы объявить тело функции, нужно использовать ключевое слово
func и никак иначе, что разумно по своим причинам. Как минимум, Вам не нужно помнить и держать в голове какая сигнатура кроется за каким типом, когда Вы смотрите на тело функции, то есть для каждого тела функции видно явно что оно должно принимать и возвращать. К тому же, дополнительная гибкость (в данном случае: объявление функции через алиасы типов, а не ключевое слово func) - это всегда удар по производительности, в данном случае - вероятное повышении времени компиляции, а для разработчиков языка это один из главных факторов, потому они очень и очень придирчиво относятся ко всем введениям и возможностям компилятора. Вон, от них даже дженериков никак допроситься не могут. Более того, выгода от возможности объявлять тело функции через алиасы типов (type aliases), а не ключевое слово func, крайне сомнительна, Вам так не кажется? К тому же не стоит путать объявление типа и объявление функции. Логично, что всегда сначала должен быть объявлен тип, а потом уже сама функция/переменная/структура, просто синтаксис языка позволяет сократить писанину. А Вы в данной ситуации хотите обойтись только созданием типа. А как тогда будете именовать входные параметры функции при её объявлении, если таковы имеются?
Выгода же абсолютно такая же, как и при других вариантах применения алиасов типов.
В первую очередь - это возможность дополнительного контроля типов.
Например: Вы разрабатываете библиотеку (свой package) и Вам нужно, чтобы какая-то функция получала на вход только те функции, которые определены у Вас в библиотеке и никакие другие. Тогда Вы создаете алиас типа на сигнатуру функции и делаете его невидимым для внешних потребителей (объявляете с маленькой буквы).
package mylib
type someFunc func() bool
var (
Apple someFunc = func() bool {
return true
}
Dog someFunc = func() bool {
return false
}
)
func Consume(f someFunc) {
f()
}
После этого внешний потребитель не сможет вызвать функцию Consume() передав туда какую угодно функцию, а только те функции, которые Вы ему приоткрыли.
package main
import "mylib"
func main() {
externalFunc := func() bool {
return true
}
mylib.Consume(externalFunc) // fail
var extF mylib.someFunc // fail
mylib.Consume(mylib.Apple) // success
}
Таким образом, обвязав свою библиотеку дополнительным контролем типов, Вы добились желаемого результата.
Во вторую очередь - это возможность сделать код более читаемым. Например, у Вас где-то есть достаточно громоздкая сигнатура и её нужно использовать во многих местах, чтобы не писать одно и то же много раз, Вы пишете сигнатуру только при объявлении функции и создании алиаса, а потом жонглируете алиасом.