Подтвердить что ты не робот

Функции вызова со специальным префиксом/суффиксом

У меня есть пакет с именем "seeder":

package seeder

import "fmt"

func MyFunc1() {
    fmt.Println("I am Masood")
}

func MyFunc2() {
    fmt.Println("I am a programmer")
}

func MyFunc3() {
    fmt.Println("I want to buy a car")
}

Теперь я хочу вызвать все функции с префиксом MyFunc

package main

import "./seeder"

func main() {
    for k := 1; k <= 3; k++ {
        seeder.MyFunc1() // This calls MyFunc1 three times
    }
}

Я хочу что-то вроде этого:

for k := 1; k <= 3; k++ {
    seeder.MyFunc + k ()
}

и этот вывод:

I am Masood
I am a programmer
I want to buy a car

EDIT1: в этом примере parentKey является строковой переменной, которая изменилась в цикле

for parentKey, _ := range uRLSjson{ 
    pppp := seeder + "." + strings.ToUpper(parentKey)
    gorilla.HandleFunc("/", pppp).Name(parentKey)
}

Но GC сказал:

использование пакетной сеялки без селектора

4b9b3361

Ответ 1

Вы не можете получить функцию по имени, и это то, что вы пытаетесь сделать. Причина в том, что если инструмент Go может обнаружить, что функция не упоминается явно (и, следовательно, недоступна), он может даже не скомпилироваться в исполняемый двоичный файл. Подробности см. В разделе " Разделение кода клиент/сервер".

С реестром функций

Один из способов сделать то, что вы хотите, это создать "реестр функций" до их вызова:

registry := map[string]func(){
    "MyFunc1": MyFunc1,
    "MyFunc2": MyFunc2,
    "MyFunc3": MyFunc3,
}
for k := 1; k <= 3; k++ {
    registry[fmt.Sprintf("MyFunc%d", k)]()
}

Вывод (попробуйте на Go Playground):

Hello MyFunc1
Hello MyFunc2
Hello MyFunc3

Ручная "маршрутизация"

Аналогично реестру проверяет имя и вручную направляет функцию, например:

func callByName(name string) {
    switch name {
    case "MyFunc1":
        MyFunc1()
    case "MyFunc2":
        MyFunc2()
    case "MyFunc3":
        MyFunc3()
    default:
        panic("Unknown function name")
    }
}

Используй это:

for k := 1; k <= 3; k++ {
    callByName(fmt.Sprintf("MyFunc%d", k))
}

Попробуйте это на игровой площадке Go.

Примечание: вам callByName() хотите ли вы вызвать функцию, callByName() по ее имени, во вспомогательной функции callByName(), или вы можете выбрать возвращение значения функции (типа func()) и вызвать ее в месте вызова.

Преобразование функций в методы

Также обратите внимание, что если ваши функции на самом деле являются методами какого-то типа, вы можете сделать это без реестра. Используя отражение, вы можете получить метод по имени: Value.MethodByName(). Вы также можете получить/перечислить все методы, не зная их имен, используя Value.NumMethod() и Value.Method() (также см. Type.NumMethod() и Type.Method() если вам нужно имя метода или типы его параметров).

Вот как это можно сделать:

type MyType int

func (m MyType) MyFunc1() {
    fmt.Println("Hello MyFunc1")
}

func (m MyType) MyFunc2() {
    fmt.Println("Hello MyFunc2")
}

func (m MyType) MyFunc3() {
    fmt.Println("Hello MyFunc3")
}

func main() {
    v := reflect.ValueOf(MyType(0))
    for k := 1; k <= 3; k++ {
        v.MethodByName(fmt.Sprintf("MyFunc%d", k)).Call(nil)
    }
}

Выход такой же. Попробуйте это на игровой площадке Go.

Ответ 2

Другой альтернативой было бы расширить диапазон ваших функций

package main

import (
    "fmt"
)

func MyFunc1() {
    fmt.Println("I am Masood")
}

func MyFunc2() {
    fmt.Println("I am a programmer")
}

func MyFunc3() {
    fmt.Println("I want to buy a car")
}


func main() {
   for _, fn := range []func(){MyFunc1, MyFunc2, MyFunc3} {
        fn()
    }
}