这是我参与「第五届青训营 」笔记创作活动的第2天,今天的课程主要讲了GO的依赖管理,还有从单元测试出发了解在项目中测试对于项目的重要性以及测试方式。
1.线程与协程之间的关系
线程:轻量级线程,栈MB级别(应用中应该是与协程相辅相成的)
协程:线程跑多个协程,栈KB级别 占用较少
根据案例我在代码中测试了一下:
func hello(i int) {
fmt.Println("hellt" + fmt.Sprint(i))
}
//在main方法中,利用多线程快速打印hello
//在方法中需要调用匿名函数完成调用
//time包下的sleep主要是让虚拟机暂停输入内容以便观察
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i + 1)
}
time.Sleep(time.Second)
c := make(chan int, 3)
fmt.Printf("c: %v\n", c)
}
从以上代码不足以得知多线程的效果,我们从下面这个例子来看
```func main() {
stc := make(chan int)
dest := make(chan int, 3)
//子协程 数据存入管道
go func() {
defer close(stc)
for i := 0; i < 10; i++ {
stc <- i
}
}()
//子协程 计算平方后存入管道
go func() {
defer close(dest)
for i := range stc {
dest <- i * i
}
}()
//遍历管道
for i := range dest {
//复杂操作
fmt.Println(i)
}
}
```js
通过上面的 管道与多线程的案例可以得知子协程之间是可以相互调用的
2.并发安全LOCK
var (
x int
lock sync.Mutex
)
func addWithLock(){
for i := 0; i < 2000; i++ {
lock.Lock()
x+=1
lock.Unlock()
}
}
func addWithoutLock(){
for i := 0; i < 2000; i++ {
x+=1
}
}
func Add(){
x=0
for i := 0; i < 5; i++ {
go addWithLock()
}
fmt.Println(x)
x=0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
fmt.Println(x)
}
根据以上代码的实验可以得出结果,在多线程操作时不上lock锁得出的结果会与预期不符,所以在多线程操作的过程中,应该注意申请lock的使用,避免数据失真。
在以上两个实验过程中,遇到了几个问题,这几个问题我认为应该是新手常见的。 第一点,课程中讲到的关于channel管道和make方法,这些都在第一节课时快速过了一遍,所以在跟进接下来的进度时,需要提前预习好golang的语法和常用包。不然后续开发的过程会十分艰难。 我目前来看就是到github上拿项目源码,再一个包一个包的Google,看看是怎么使用,在上面场景使用。虽然效率不高,但我目前也没有其他方法。如果同学们有其他方法,可以给我留言一下,十分感谢。最后祝大家学习进步,顺利结营。