原计划,继续将 Go+ 的手册在翻译一下,结果发现没了~,为了继续学习,那只能用 Go+ 写一个爬虫了。
GoPlus 爬虫
本次要采集站点为 Go+ 的手册,地址为:https://tutorial.goplus.org/,采集该站点需要用到 Go+ 的包。
这一部分的实现 ,Go+ 与 Go 基本一致,完整代码如下所示:
import (
"io/ioutil"
"net/http"
"regexp"
)
resp, err := http.Get("https://tutorial.goplus.org/")
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
println("read error", err)
return
}
//println(string(body))
pattern := `<li><a class="example-link" href="\/(.*?)">(.*?)</a></li>`
reg := regexp.MustCompile(pattern)
items := reg.FindAllString(string(body), -1)
println(items)
for _, item <- items {
println item
}
其中涉及 io/ioutil
, net/http
, regexp
包的使用,编写这部分过程中,发现Go+与Go的兼容性还是蛮强的。
但也碰到了一个比较绕的地方,如果能有官方团队辅助解答一下就非常 nice 。
案例已经写完,下面翻译一下 Error-Handling
的官方手册。
Go+ 重写编写了Go的错误处理规范,并将其称之为 ErrWrap expressions
。
查阅相关内容之后,找到了如下这篇文章
https://github.com/goplus/gop/wiki/Error-Handling
Error Handling(错误处理)
Go+ 中重新发明了错误处理规范,称之为 ErrWrap expressions
expr! // panic if err
expr? // return if err
expr?:defval // use defval if err
使用案例
import (
"strconv"
)
func add(x, y string) (int, error) {
return strconv.Atoi(x)? + strconv.Atoi(y)?, nil
}
func addSafe(x, y string) int {
return strconv.Atoi(x)?:0 + strconv.Atoi(y)?:0
}
println(`add("100", "23"):`, add("100", "23")!)
sum, err := add("10", "abc")
println(`add("10", "abc"):`, sum, err)
println(`addSafe("10", "abc"):`, addSafe("10", "abc"))
案例的输出内容
add("100", "23"): 123
add("10", "abc"): 0 strconv.Atoi: parsing "abc": invalid syntax
===> errors stack:
main.add("10", "abc")
/Users/xsw/goplus/tutorial/15-ErrWrap/err_wrap.gop:6 strconv.Atoi(y)?
addSafe("10", "abc"): 10
与相应的 Go 代码相比,它更清晰、更具可读性。
最有趣的是,返回错误包含完整的错误堆栈。当我们遇到错误时,很容易定位根本原因是什么。
上述内容是官方自带的翻译,下面进入正题。
如何使用 ErrWrap expressions
?
所有的 ErrWrap expressions
都假设 expr
(大多数情况下,它是一个函数调用)具有多个值(val1, val2,…, valN),而 valN
可以赋给一个 error
变量。
expr!
表达式用来检查 valN
是否为 nil
,如果不是,就会抛出异常,即程序发生错误(panic),下面是一个 Go 的案例
val1, val2, ..., valN1, valN := expr
if valN != nil {
panic(errors.NewFrame(valN, ...))
}
val1, val2, ..., valN1 // value of `expr!`
expr?
表达式 检查 valN
是否为 nil
,如果不是,则返回错误,该语法需要 exor?
表达式返回的参数具备 error
类型,下面是对应的Go代码。
val1, val2, ..., valN1, valN := expr
if valN != nil {
_ret_err = errors.NewFrame(valN, ...)
return
}
val1, val2, ..., valN1 // value of `expr?`
expr?:defval
表达式检查 valN
是否为 nil
,如果不是,它使用 defval
作为表达式 expr
的值,所以它需要 expr
表达式有两个值 (val1, val2)
。
val1, val2 := expr
if val2 != nil {
val1 = defval
}
val1 // value of `expr?:defval`
写在后面
今天是持续写作的第 275 / 365 天。
可以关注我,点赞我、评论我、收藏我啦。