想为 golang 添加一个错误处理语法糖 !err, 大家来看看这种错误处理方式如何

2023-08-31 08:01:18 +08:00
 sofukwird

简介

这是一个为 Go 添加 !err 错误处理语法糖的项目, 与 Go 完全兼容(毕竟只是语法糖)

有了它你可以写如下代码, 代码更加紧凑 阅读更轻松

转换前:

package main

import (
  "fmt"
  "os"
)

func main() {
  body, !err := readSelf()
  fmt.Println("main.go content")
  fmt.Println(body)
}

func readSelf() (content string, err error) {
  body, !err := os.ReadFile("main.go")
  content = string(body)
  return
}

转换后:

package main

import (
  "fmt"
  "os"
)

func main() {
  body, err := readSelf()
  if err != nil {
    return
  }
  fmt.Println("main.go content")
  fmt.Println(body)
}

func readSelf() (content string, err error) {
  body, err := os.ReadFile("main.go")
  if err != nil {
    return
  }
  content = string(body)
  return
}


项目地址: https://github.com/gone-lang/gone

先来问问各位大佬的意见, 看下怎么做比较好

4143 次点击
所在节点    Go 编程语言
36 条回复
learningman
2023-08-31 10:53:24 +08:00
你这样不如
v, ? := xxx()
guonaihong
2023-08-31 11:16:44 +08:00
现在一堆 ai 辅助编程的插件 感觉收益不是那么明显。copilot 一个回车解决的事情。
codersdp1
2023-08-31 11:46:19 +08:00
func readSelf() (string, error) {
body, err := os.ReadFile("main.go")
if err != nil {
return "",err
}
content = string(body)
return content,nil
}

这种怎么处理 🤔️
PTLin
2023-08-31 12:32:03 +08:00
https://github.com/golang/go/issues?q=label%3Aerror-handling
看看这些数不清的提案,相信总有一个是比你这个想法优秀且被枪毙了的。
sofukwird
2023-08-31 13:09:05 +08:00
@codersdp1 #23 这种情况不使用语法糖,直接使用你现在使用的代码,这个糖是有限的,不打算应对所有情况

@guonaihong 主要还是想阅读的时候更简单轻松,虽然编辑器能补全但代码行数是实打实地变多了

@fioncat 不选择 v := xxx()? 是因为它假定了最后返回 error ,而且在只返回 error 的情况下可读性并不好,需要看到末尾才知道这行是否可能出错

xxx()?

@learningman 不选择 v, ? := xxx() 则是因为转译后需要自己生成 err 临时变量名并返回,临时变量名会千奇百怪的导致可读性下降。那使用 v, ?err := xxx() ?我一开始就是提议的这种后来发现 v, !err := xxx() 这种可读性更好。

我选择这种模式是因为它易于实现,又或者说正是因为它易于实现我才能选择它
raies
2023-08-31 13:35:56 +08:00
不如这样

body := readSelf()?
ck65
2023-08-31 13:48:51 +08:00
感觉无糖更方便,因为我已经告诉别人我是 Errlang 开发者了。
index90
2023-08-31 16:16:28 +08:00
FP 才是最优解:
type Result[T any] struct { v T; err error }
func(r *Result[T]) IfErr(f func(error)) { if r.err != nil {f(err)} }
func fmap[A, B any](ra Result[A], f f(a) Result[B]) Result[B] {
if ra.err != nil { return f(ra.v) }
return Result[B]{err: error}
}
liuguang
2023-08-31 16:23:48 +08:00
设计上用元组就是一个大的失误,值和错误不会同时出现。
而 rust 的枚举就是很好的设计,rust 的问号运算符也是一个好的语法糖。
mcfog
2023-08-31 16:59:48 +08:00
@liuguang 偶尔会同时出现的,例如读写 socket 、文件可以失败的同时已经成功了一部分

不过我同意还是支持代数数据类型能解决不少问题
Mohanson
2023-08-31 18:25:01 +08:00
对于编程语言来说, 除非你有充分的理由, 否则不要加语法糖.

注: 我觉得这样写很 cool 就不是一个充分的理由.
mainjzb
2023-08-31 18:46:01 +08:00
https://github.com/golang/go/issues/62253
你的想法已经被毙过了
aduo
2023-08-31 19:24:53 +08:00
想法挺好的... 但是没有明确的 return 语句却可能会 return ,有点孩怕, 感觉容易出事故
sofukwird
2023-08-31 20:13:46 +08:00
@ck65 golang 称为 err-lang 也确实是实至名归,1/5 的代码行数是由 if err != nil {} 提供的
第一眼看成了 erlang 略过去了

@mainjzb 拒绝的理由是我们已经拒绝过了这项提案,泛型也是被拒绝过的现在也加上去了。
正如 issue 里提到的回复:“golang 不会根据各种错误处理提案的喜爱程度对错误处理进行改进,golang 有自己的节奏”

@aduo panic 也会导致函数提前返回,相对于使用 panic 的错误处理方案 !err 不会有性能损失
joesonw
2023-08-31 22:24:03 +08:00
最关键的问题是,一般是鼓励 wrap 一下错误,不然你只看到 io 错误,根本不知道是哪里的问题,排查起来头痛。
mainjzb
2023-09-01 09:41:32 +08:00
我也会拒绝你,你这等于给语言加了一个宏仅仅为了偷懒少写一些代码而已。
当然 go 的初期设计确实考虑的很简陋,更聪明一点的做法是像 zig 或 rust 那样。
go error 设计更大的问题是没有保存堆栈。对于仅仅多写一点代码的问题,完全可以用 ide 来自动补充来解决。
无论是你的设计还是 rust 的设计还是 zig 的设计,还是当前 go 的设计,都不影响阅读代码。 写代码只是为了偷懒,我认为没有完全的必要性添加此项更改。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/969638

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX