提案:将抛出作为Go语言中自动错误传播的特殊变量

2作者: iondodon14 天前原帖
提案:通过 `throw` 标识符在 Go 中隐式错误传播 <p>摘要</p> 本提案引入了一种新的语法约定:在变量声明或赋值中使用标识符 `throw`(例如,`result, throw := errorFunc()`)。当编译器检测到这一用法时,将自动插入对非零错误的检查,并返回所有非错误返回值的零值以及错误。这一机制简化了错误处理,同时不妨碍 Go 语言一贯的明确性和可读性。 <p>动机</p> Go 鼓励显式的错误处理,这常常导致重复的样板代码。例如: <p>result, err := errorFunc() if err != nil { return zeroValue, err }</p> 这种模式虽然清晰,但增加了冗长性,可能会影响可读性,尤其是在包含多个易出错调用的函数中。通过引入一种保留清晰度的语法简写,我们可以减少样板代码,提高开发者的工作效率。 <p>提案</p> 当一个名为 `throw` 的变量被赋值为返回 `error` 的函数的结果,并且外层函数返回一个 `error` 时,编译器将隐式插入: <p>if throw != nil { return zeroValues..., throw }</p> <p>适用场景</p> 短声明: <pre><code> x, throw := doSomething() </code></pre> 标准赋值: <pre><code> x, throw = doSomething() </code></pre> 带赋值的变量声明: <pre><code> var x T; var throw error; x, throw = doSomething() </code></pre> * `throw` 必须是 `error` 类型的变量 * 外层函数必须返回一个 `error` * 该规则仅适用于变量名明确为 `throw` 的情况 <p>示例</p> 传统错误处理: <pre><code>func getUserData(id int) (data Data, err error) { data, err := fetch(id) if err != nil { return Data{}, err } return data, nil }</code></pre> 使用 `throw`: <pre><code>func getUserData(id int) (Data, error) { data, throw := fetch(id) // 自动扩展为:if throw != nil { return Data{}, throw } moreData, throw := fetchMore(id) // 自动扩展为:if throw != nil { return Data{}, throw } return data, nil }</code></pre>
查看原文
Proposal: Implicit Error Propagation via `throw` Identifier in Go<p>Abstract<p>This proposal introduces a new syntactic convention to Go: the use of the identifier `throw` in variable declarations or assignments (e.g., `result, throw := errorFunc()`). When detected, the compiler will automatically insert a check for a non-nil error and return zero values for all non-error return values along with the error. This mechanism streamlines error handling without compromising Go&#x27;s hallmark of explicit, readable code.<p>Motivation<p>Go encourages explicit error handling, which often results in repetitive boilerplate code. For example:<p>result, err := errorFunc() if err != nil { return zeroValue, err }<p>This pattern, while clear, adds verbosity that can hinder readability, especially in functions with multiple error-prone calls. By introducing a syntactic shorthand that preserves clarity, we can reduce boilerplate and improve developer ergonomics.<p>Proposal<p>When a variable named `throw` is assigned the result of a function returning an `error`, and the enclosing function returns an `error`, the compiler will implicitly insert:<p>if throw != nil { return zeroValues..., throw }<p>Applicable Scenarios<p>Short declarations:<p><pre><code> x, throw := doSomething() </code></pre> Standard assignments:<p><pre><code> x, throw = doSomething() </code></pre> Variable declarations with assignment:<p><pre><code> var x T; var throw error; x, throw = doSomething() </code></pre> * `throw` must be a variable of type `error`<p>* The surrounding function must return an `error`<p>* The rule only applies when the variable is explicitly named `throw`<p>Example<p>Traditional Error Handling<p>func getUserData(id int) (data Data, err error) { data, err := fetch(id) if err != nil { return Data{}, err } return data, nil }<p>With `throw`<p>func getUserData(id int) (Data, error) {<p><pre><code> data, throw := fetch(id) &#x2F;&#x2F; Automatically expands to: if throw != nil { return Data{}, throw } moreData, throw := fetchMore(id) &#x2F;&#x2F; Automatically expands to: if throw != nil { return Data{}, throw } return data, nil }</code></pre>