Можем ли мы иметь указатели на функции в Go?
Я изучал указатели в Go. И удалось написать что-то вроде:
func hello(){
fmt.Println("Hello World")
}
func main(){
pfunc := hello //pfunc is a pointer to the function "hello"
pfunc() //calling pfunc prints "Hello World" similar to hello function
}
Есть ли способ объявить указатель функции, не определяя его, как сделано выше?
Можем ли мы написать что-то похожее на C?
например void (*pfunc)(void);
Ответы
Ответ 1
Он работает, если вы используете подпись. Нет указателя.
type HelloFunc func(string)
func SayHello(to string) {
fmt.Printf("Hello, %s!\n", to)
}
func main() {
var hf HelloFunc
hf = SayHello
hf("world")
}
В качестве альтернативы вы можете напрямую использовать подпись функции, не объявляя новый тип.
Ответ 2
Go не имеет такой же синтаксис для указателей на функции, как C и C++. Это очень хорошее объяснение в блоге Go. Понятно, что авторы Go считали синтаксис C для указателей на функции слишком похожим на обычные указатели, поэтому вкратце они решили сделать указатели на функции явными; то есть более читабельным.
Вот пример, который я написал. Обратите внимание, как параметр fp
определен в calculate()
и в другом примере ниже, который показывает вам, как вы можете сделать указатель на функцию в типе и использовать его в функции (функция вычисления с комментариями).
package main
import "fmt"
type ArithOp func(int, int)int
func main() {
calculate(Plus)
calculate(Minus)
calculate(Multiply)
}
func calculate(fp func(int, int)int) {
ans := fp(3,2)
fmt.Printf("\n%v\n", ans)
}
// This is the same function but uses the type/fp defined above
//
// func calculate (fp ArithOp) {
// ans := fp(3,2)
// fmt.Printf("\n%v\n", ans)
// }
func Plus(a, b int) int {
return a + b
}
func Minus(a, b int) int {
return a - b
}
func Multiply(a,b int) int {
return a * b
}
Параметр fp
определяется как функция, которая принимает два целых числа и возвращает одно целое число. Это примерно то же самое, что упоминалось Mue, но показывает другой пример использования.
Ответ 3
Вы можете сделать это следующим образом:
package main
import "fmt"
func hello(){
fmt.Println("Hello World")
}
func main(){
var pfunc func()
pfunc = hello //pfunc is a pointer to the function "hello"
pfunc()
}
Если ваша функция имеет аргументы и, например, возвращаемое значение будет выглядеть так:
func hello(name string) int{
fmt.Println("Hello %s", name)
return 0
}
и переменная будет выглядеть так:
var pfunc func(string)int
Ответ 4
Функция также является типом в Go. Таким образом, вы можете создать переменную сигнатуры типа func
. Следующее будет работать;
var pfunc func(string)
Эта переменная может указывать на любую функцию, которая принимает строку в качестве аргумента и ничего не возвращает. Следующий фрагмент кода работает хорошо.
package main
import "fmt"
func SayHello(to string) {
fmt.Printf("Hello, %s!\n", to)
}
func main() {
var pfunc func(string)
pfunc = SayHello
pfunc("world")
}
Ответ 5
Другой способ подойти к этому - определить интерфейс
type command interface {
DoLoop()
}
реализовать структуру, которая реализует ее
type Delete struct {
instance string
}
func (dev Delete) DoLoop() {
fmt.Println("input: delete ")
}
Создайте карту, которая содержит структуру
mainFuncTable = make(map[string]command)
mainFuncTable["delete"] = Delete{"new"}
вызов функции
func route(command string) {
cmd := mainFuncTable[command]
cmd.DoLoop()
}
Это немного косвенно, но это работает