【问题标题】:Return void function with result of another void function?用另一个 void 函数的结果返回 void 函数?
【发布时间】:2016-04-22 09:58:59
【问题描述】:

我正在尝试提出一种非常紧凑的方法来处理可能在对 REST API 的 HTTP 请求中出现的问题。

我需要测试许多条件,以及针对任何这些条件失败的许多潜在错误响应。

我的处理流程类似于以下内容:

// Error is actually a method on some struct, so it's only relevant for demonstration purposes.
func Error(w http.ResponseWriter, status int, message string) {
  // Lots of stuff omitted
  w.WriteHeader(status)
  w.WriteJson(r)
}

func HandleSomething(w http.ResponseWriter, r *http.Request) {
  if someCondition != true {
    Error(w, 500, "Some error occurred!")
    return
  }
  if someOtherCondition != true {
    Error(w, 500, "Some other error occurred!")
    return
  }
  if yetAnotherCondition != true {
    Error(w, 500, "Yet another error occurred!")
    return
  }
  if andFinallyOneLastCondition != true {
    Error(w, 500, "One final error occurred!")
    return
  }
  // All good! Send back some real data.
  w.WriteJson(someObject)
}

由于我经常需要测试 5-10 个条件,以及在其他操作期间可能出现的其他错误,因此能够将其压缩为以下内容会很不错:

func HandleSomething(w http.ResponseWriter, r *http.Request) {
  if someCondition != true {
    return Error(w, 500, "Some error occurred!")
  }
  if someOtherCondition != true {
    return Error(w, 500, "Some other error occurred!")
  }
  if yetAnotherCondition != true {
    return Error(w, 500, "Yet another error occurred!")
  }
  if andFinallyOneLastCondition != true {
    return Error(w, 500, "One final error occurred!")
  }
  // All good! Send back some real data.
  w.WriteJson(someObject)
}

但是,Go 编译器不喜欢这样。

它抱怨我试图将Error() 的结果用作值,并且我试图返回太多参数。确切的错误消息是:

foo.go:41: bar.Response.Error(400, "InvalidRequest", "Error decoding request") used as value
foo.go:41: too many arguments to return

但是Error() 和HandleSomething() 都具有相同的返回签名(例如,它们都没有返回任何内容),所以这不应该工作吗?

每个if 语句都包含一个return 很重要,因为该函数应该立即退出。如果Error() 可以以某种方式停止调用函数的执行,那也对我有用。有点像testing.FailNow(),但我相信这依赖于 Goroutines。

顺便说一句:我意识到这些并不是真正的“无效”函数,但想不出更合适的名称。 Go 中不返回任何内容的函数是否有合适的名称?

【问题讨论】:

  • go 中什么也不返回的函数就是这样。它没有名字,因为它本身并没有什么特别之处。

标签: go idioms


【解决方案1】:

我不确定,但我会用 if-else 方式来做

func HandleSomething(w http.ResponseWriter, r *http.Request) {
  if someCondition != true {
    Error(w, 500, "Some error occurred!")
  } else if someOtherCondition != true {
    Error(w, 500, "Some other error occurred!")
  } else if yetAnotherCondition != true {
    Error(w, 500, "Yet another error occurred!")
  } else if andFinallyOneLastCondition != true {
    Error(w, 500, "One final error occurred!")
  } else {
    // All good! Send back some real data.
    w.WriteJson(someObject)
  }
}

【讨论】:

    【解决方案2】:

    C++ 允许这样做。对于模板来说非常方便。

    但正如你所见,Go 没有。我不确定确切的步骤,但这似乎是您可以要求添加到 Go 中的东西,也许它可以在 1.7 中使用。

    至于现在的解决方案,也许您可​​以返回未使用的error。只需从您的 Error 函数中将其返回为 nil。

    【讨论】:

    • 如你所见,go 语言已经基本完成,而且更改的接受度非常高。不太可能接受对语言规范进行例外以实质上保存换行符。
    • @JimB:Go 允许空返回。它只是不允许从另一个函数返回空返回。这对我来说似乎不是一个大的变化。至少可以尝试看看是否可以进行更改。
    • @DC_:return statement 可能包含 0 个或多个 expressions。根据定义,表达式会产生一个值。同样在规范中:“在没有结果类型的函数中,“返回”语句不得指定任何结果值”。即使是很小的语言更改也可能会产生意想不到的后果,需要在该语言的生命周期内进行维护,并且将 2 行压缩为一个可能需要付出很大的代价(请注意,组合 for+select 以保存一行的建议已经也被拒绝了)
    猜你喜欢
    • 2023-01-28
    • 2016-08-28
    • 2021-06-06
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 2015-01-24
    相关资源
    最近更新 更多