dopuzf0898
2019-02-20 18:14 阅读 93
已采纳

在golang中运行多个条件函数

I would like to run workflow functions using 5 functions in golang

  1. init
  2. validate
  3. process
  4. execute
  5. finalize

Each method should return the same result object and error object in case of failure

I would like to find a pattern to run this workflow rather than doing the following:

if result, err := init(); err != nil {
    if result, err := validate(); err != nil {
       if result, err := process(); err != nil {
           if result, err := execute(); err != nil {
               if result, err := finalize(); err != nil {

               }
           }
       }
    }
}

Thanks in advance Peter

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

2条回答 默认 最新

  • 已采纳
    dongyan0629 dongyan0629 2019-02-20 21:29

    You can create a slice of functions and make this whole process prettier, e.g.

    functions := []func() (string, error){
        function1, function2, function3, function4, function5,
    }
    for _, function := range functions {
        someValue, err := function()
        if err != nil {
            fmt.Println("Function " + someValue + " didn't feel so good.")
            break
        }
        fmt.Println("Function " + someValue + " went all right!")
    }
    

    In short, the break stops things from going on, if you wrap the above process as a function, you could also use something like

    return false
    

    in case of an error, and at the end of the total amount of iterations, say i == len(functions) -1, you could return true if everything went all right.

    It is noteworthy to mention that you can only create slice of functions that satisfies these conditions:

    • They all must have the same amount of arguments;

    • All arguments must have the same type per position;

    • They all have the same amount of return values;

    • Likewise, they (return values) must have the same type per position;

    Still, you can easily overcome these limitations by having two or three different slices. For example, function1 to function3 can all be classified as

    func () (bool, err)
    

    Where function4 and 5 are

    func () (int, err)
    

    For these functions to work you could just reiterate the first slice, then if everything goes as planned, move on to the second.

    firstSetOfFuncs := []func() (bool, error){
        function1, function2, function3,
    }
    secondSetOfFuncs := []func() (int, err){
        function4, function5,
    }
    for i, function := range firstSetOfFuncs {
        someValue, err := function()
        if err != nil {
            fmt.Println("Something went terribly wrong.")
            break
        }
        if i == len(firstSetOfFuncs) - 1 {
            for _, secondTypeOfFunc := range secondSetOfFuncs {
                someNum, anotherErr := secondTypeOfFunc()
                if anotherErr != nil {
                    fmt.Println("All seemed all right, until it didn't.")
                    break
                }
            }
        }
    }
    
    点赞 评论 复制链接分享
  • doufen1933 doufen1933 2019-02-20 21:20

    As i allready said in a comment, i think the most idiomatic way would be to just call a method, check for errors. And if there was an error return it. You can of course use the simplified error handling version, like you used in your question, but even if you do that. Try to avoid that deep nesting. It's hard to read & understand (deeply) nested code.

    result,err := init()
    if err != nil {
      return nil, err // An error occured so handle it
    }
    
    result,err = validate()
    if err != nil {
      return nil, err
    }
    
    
    result,err = process()
    if err != nil {
      return nil, err
    }
    
    
    result,err = execute()
    if err != nil {
      return nil, err
    }
    
    result,err = finalize()
    if err != nil {
      return nil, err
    }
    

    Problems of your example code

    You've done the error checking wrong. You are checking for

    if err != nil

    Spoken "if there is an error". And you continue with your code, although there is an error.

    To fix that you need to write:

    var result someType
    
    if result, err := init(); err != nil {
      return nil, err // An error occured so handle it
    }
    
    if result, err := validate(); err != nil {
      return nil, err
    }
    
    
    if result, err := process(); err != nil {
      return nil, err
    }
    
    if result, err := execute(); err != nil {
      return nil, err
    }
    
    if result, err := finalize(); err != nil {
      return nil, err
    }
    
    点赞 评论 复制链接分享

相关推荐