Карта строк и обобщенных функций в Голанге - PullRequest
0 голосов
/ 10 октября 2018

Я пытаюсь создать карту, которая будет отображать строки в функции.Не все функции имеют одинаковую подпись.Например, я хотел бы иметь что-то вроде этого:

rf := map[string]func(...interface{}) error{
    "FirstName":        validateExistence(a.FirstName, "FirstName is required."),
    "Postcode":         validateMatchPattern(a.Postcode, `^\d{5}$`, "Could not match pattern for postcode."),
    "Address":          validateLength(a.Address, 0, 35, "Address must have up to 35 chars."),
}

Я получаю эту ошибку:

cannot use validateExistence("FirstName is required.") (type func(string) error) as type func(...interface {}) error in map value

Если я изменю объявление карты на map[string]func(f string, m string) error, ошибкадля FirstName решена, но я получаю другие ошибки для двух других функций:

cannot use validateMatchPattern(a.Postcode, "^\\d{5}$", "Could not match pattern for postcode.") (type error) as type func(string) error in map value
cannot use validateLength(a.Address, 0, 35, "Address must have up to 35 chars.") (type error) as type func(string) error in map value

Я понимаю, что проблема в объявлении карты, в func(...interface{}), чтобы быть более точным.Эта часть должна иметь те же подписи, что и функция, которую я использую в качестве ключа.

Итак, мой вопрос: есть ли другой способ объявить карту, которая может содержать функции с разными сигнатурами?

1 Ответ

0 голосов
/ 10 октября 2018

Если бы я проектировал это, я бы разбил эту проблему следующим образом:

  1. Я хочу карту валидаторов, каждый из которых принимает строку и возвращает читаемую человеком ошибку.
  2. Я хочу соединить простой валидатор, который возвращает ответ «да» или «нет» с сообщением об ошибке.
  3. Мне нужен набор простых валидаторов.

Обратите внимание, что во всех этих случаях вам нужны функции, которые возвращают функции.Например, валидатор длины может быть:

func validateLength(min, max int) func(string) bool {
        return func(s string) bool {
                return len(s) >= min && len(s) <= max
        }
}

Затем вы можете обернуть это в функцию, которая выдает ошибку

func makeValidator(f func(string) bool, msg string) func(string) error {
        return func(s string) error {
                if !f(s) {
                        return errors.New(msg)
                }
                return nil
        }
}

Теперь у вас есть пара слоев, которые создаютфункции, которые входят в карту, так что вы можете создать

rt := map[string]func(string) error {
        "Address": makeValidator(
                validateLength(0, 35),
                "Address must have up to 35 chars."
        )
}

Это не связывает его с конкретным полем (и, действительно, предложение из комментариев просто написать это в коде, вероятно, является хорошим), ноесли вам нужно, чтобы это было действительно универсально, вы можете использовать отражение для просмотра содержимого структуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...