我的Go+语言初体验——Go+,GoPlus 爬虫第一例

原计划,继续将 Go+ 的手册在翻译一下,结果发现没了~,为了继续学习,那只能用 Go+ 写一个爬虫了。

我的Go+语言初体验——Go+,GoPlus 爬虫第一例

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/ioutilnet/httpregexp 包的使用,编写这部分过程中,发现Go+与Go的兼容性还是蛮强的。

我的Go+语言初体验——Go+,GoPlus 爬虫第一例

但也碰到了一个比较绕的地方,如果能有官方团队辅助解答一下就非常 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 天。
可以关注我,点赞我、评论我、收藏我啦。

“我的Go+语言初体验” | 征文活动进行中…

上一篇:Doris-bitmap的应用场景


下一篇:ANTLR 语法设计