- 国内代理
1 | go env -w GO111MODULE=on |
https://github.com/goproxy/goproxy.cn/blob/master/README.zh-CN.md
- 获取一个目录下的所有依赖
旧项目没有 go modules,需要使用这个命令
1 | go get -d ./... |
...
表示是递归地获取所有目录。
1 | go env -w GO111MODULE=on |
https://github.com/goproxy/goproxy.cn/blob/master/README.zh-CN.md
旧项目没有 go modules,需要使用这个命令
1 | go get -d ./... |
...
表示是递归地获取所有目录。
go 的编程中,常常会在一个 goroutine 中启动多个 goroutine,然后有可能在这些 goroutine 中又启动多个 goroutine。
如上图,在 main 函数中,启动了一个 goroutine A 和 goroutine B,然后 goroutine A 中又启动了 goroutine A1 和 goroutine A2,goroutine B 中也是。
有时候,我们可能想要取消当前的处理,这个时候自然而然的也要取消子协程的执行进程。这个时候就需要一种机制来做这件事。context 就是设计来做这件事的。
比如在 web 应用中,当子协程的某些处理时间过长的时候,我们可能想要终止下游的处理,防止协程长期占用资源。保证其他客户端的请求正常处理。
往往用做父 context,比如在 main 中定义的 context,然后在 main 中将这个 context 传递给子协程。
不需要使用什么类型的 context 的时候,使用这个 context.TODO
我们需要对子 goroutine 做一些超时控制的时候,使用这个 context,比如超过多少秒就不再做处理。
和 context.WithTimeout 类似,只不过参数是一个 time.Time,而不是 time.Duration
如果在父 goroutine 里面需要在某些情况下取消执行的时候,可以使用这种 context。
1 | package main |
在 main 入口里顶层的 context 使用 context.Background,子 goroutine
里面可以针对实际情况基于父 context 派生新的
context,比如,加入如果需要对子 goroutine
做一些条件性的取消操作,就可以像上面那样使用
ctx3, cancel := context.WithCancel(ctx2)
来基于父 context
创建一个新的 context,然后我们可以通过 cancel 来给子 goroutine
发送取消信号。
注意这里的用语,这里说发送取消信号,因为事实上是否取消后续操作的控制权还是在子 goroutine 里面。但是子 goroutine 有义务停止当前 goroutine 的操作。
个人觉得一个原因是,可能子 goroutine 里面有一些清理操作需要进行,比如写个 Log 说当前操作被取消了,这种情况下直接强行取消并不是很好的选择,所以把控制权交给子 goroutine。
这一点可能在大多数文章里面可能没有提到,但是笔者觉得如果明白了这一点的话,对于理解 context 的工作机制很有帮助。
这种机制的感觉有点像是,虽然你有权力不停止当前操作,但是你有义务去停止当前的处理,给你这种权力只是为了让你有点反应时间。
这个就跳过吧,好像没什么好说的
1 | func ExampleContextWithTimeout() { |
1 | func ExampleContextWithDeadline() { |
1 | func ExampleContextWithCancel() { |
其实我们可以发现,context.WithTimeout 和 context.WithDeadline 也返回了一个 cancelFunc,context.WithCancel 返回的 cancelFunc 和这个的效果一样。
只不过 context.WithTimeout 和 context.WithDeadline 多提供了一个时间上的控制。
golang 中的 context 提供了一种父子 goroutine 之间沟通的机制
context.WithTimeout、context.WithDeadline、context.WithCancel 都返回一个新的 context 和一个 cancelFunc,cancelFunc 可以用来取消子 goroutine
goroutine 最终是否停止取决于子 goroutine 本身,但是我们有必要去监听 ctx.Done() 来根据父 goroutine 传递的信号来决定是否继续执行还是直接返回。
在单元测试中,我们有时候可能需要使用多组测试数据来测试同一个功能,在
pytest 中可以使用 @pytest.mark.parametrize
装饰器来装饰一个类或者方法来传递多组测试数据来测试同一个功能。
test_1.py
1 | import pytest |
运行代码:
1 | pytest -sv test_1.py |
输出:
1 | tests/aa/test_aa.py::test_parametrize_1[1-2-3] |
在这个例子中,我们定义了一个数组,里面保存了两个元组,同时在测试函数上面使用了
@pytest.mark.parametrize('a, b, expect', data)
来装饰。 这个情况下,pytest 会循环 data 数据,把里面的每一项的数据拿出来,传递给test_parametrize_1
运行。
实际效果可以看作如下伪代码:
1 | for value in data: |
如果只有一个参数,那就更简单了:
1 | import pytest |
输出:
1 | tests/aa/test_aa.py::test_parametrize_1[1] |
1 | import pytest |
输出:
1 | tests/aa/test_aa.py::test_parametrize_1[value0] |
这里的 value 参数直接接收了 data 里面的每一项。
和第一种 @pytest.mark.parametrize('a, b, expect', data)
的区别是,这里的 value 接收了 [a, b, expect]
这个数组作为值。
@pytest.mark.parametrize
也可以用于装饰类,这样一来,该类中的测试方法就都有了这些参数,等同于给该类中的每一个测试方法加上
@pytest.mark.parametrize
。
例子
1 | import pytest |
输出
1 | tests/aa/test_aa.py::TestParametrize::test_parametrize_1[value0] |
这个在第一小节中已经提及
我们在上面的测试中发现一些输出内容如下面的格式:
1 | tests/aa/test_aa.py::TestParametrize::test_parametrize_1[value0] |
后面有个方括号来表示当前测试的是第几组参数。这个我们可以自定义格式:
1 | import pytest |
输出
1 | tests/aa/test_aa.py::TestParametrize::test_parametrize_1[a=1, b=2, expect=3] |
这样一来我们的输出就更加的直观了。
输出的时候需要添加
-sv
参数,如pytest -sv tests/aa/test_aa.py
1 | $res = NULL; |
产生原因是给一个值为 null 的变量设置属性。
先看看源码
1 | // D is an ordered representation of a BSON document. This type should be used when the order of the elements matters, |
在 Go MongoDB Driver 中,我们调用 MongoDB Driver
提供的方法的时候,往往需要传入 bson.D
, bson.A
,
bson.M
, bson.A
这几种类型。
用来表示一个有序的 BSON 文档,当我们需要传递一些有序的参数的时候可以使用,比如 MongoDB 中的聚合操作,聚合操作往往是一组操作的集合,比如先筛选、然后分组、然后求和,这个顺序是不能乱的。
用来表示 bson.D 中的一个属性,类型定义如下:
1 | // E represents a BSON element for a D. It is usually used inside a D. |
可以类比 json 对象里面的某一个属性以及其值。
首先,bson.M 其实是一个 map,不接受这种类型,bson.D 实际上是 []bson.E 类型,是 bson.E 的切片。
其次,bson.M 里面是顺序无关的,普通的 map 就已经足够了,没必要再定义一个类型。
用来表示无需的 BSON 文档,就是一个普通的 map 类型。在保存到 MongoDB 中的时候,字段顺序是不确定的,而 bson.D 的顺序是确定的。
顺序可能大部分情况都是不需要的。不过在匹配嵌套的 BSON 数组文档的时候,可能会有问题。但还是有其他的解决办法的。
可参考本站的: MongoDB $elemMatch 操作符
用来表示 BSON 文档中的数组类型,是有序的。