Golang中的字符串和通用函数的映射

时间:2018-10-10 10:37:05

标签: go

我正在尝试创建一个将字符串映射到函数的映射。并非所有功能都具有相同的签名。例如,我想要这样的东西:

   [FunctionName("E1_Todo")]
    public static async Task<TestToDo> RunToDo(
    [OrchestrationTrigger] DurableOrchestrationContextBase context,
        ILogger log)
    {
        HttpReq r = context.GetInput<HttpReq>();
        TestToDo todo = new TestToDo();
        if(r != null)
        {
            todo = await context.CallActivityAsync<TestToDo>("E1_CallAPITodo",r);
        }
        return todo;
    }

[FunctionName("E1_CallAPITodo")]
public async static Task<TestToDo> APITodoCall([ActivityTrigger] HttpReq req,
    ILogger log)
{

    var request = new HttpRequestMessage(HttpMethod.Get, "https://jsonplaceholder.typicode.com/todos/1");
    request.Headers.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json")
    );
     log.LogInformation($"URL calling = '{request.RequestUri.AbsoluteUri}'. for {req.QueryString}");
    HttpResponseMessage response = await client.SendAsync(request);
    return await response.Content.ReadAsAsync<TestToDo>();
} 

我收到此错误:

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 中。这部分必须与我用作键的功能具有相同的签名。

所以,我的问题是:还有其他方法可以声明可以容纳具有不同签名的函数的映射吗?

1 个答案:

答案 0 :(得分:1)

如果我正在设计这个,我会像这样分解这个问题:

  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."
        )
}

这不会与特定字段配对(确实,注释中的建议只是用代码编写此字段可能是一个不错的选择),但是如果您真的需要泛型,可以使用reflection看一下结构的内容。