背景:有一篇朋友圈说是一个k8s里面Server的Pod销毁上报Zookeeper出现IP地址连接还是原来的,用到了zk的watcher,理论上不应该这样,于是查来查去,其大体意思就是说用了Go的多进程,有一个进程去读取配置了,因为配置还是老的,而用到了Go的多进程,于是文末那代码,我看了下,简单,但不明白,于是顺藤摸瓜学习一下这个rsync的原理。
——————————
#tree -L 2 .|grep go
├── loop.go
├── pipe.go
├── waitgrouppointer.go
└── wg.go
#cat loop.go
package main
import (
"fmt"
//"time"
)
func main(){
for i := 0; i < 100 ; i++{
go fmt.Println(i)
}
//time.Sleep(time.Second)
}
这个说是运行太快,子进程没输出主进程就退了,啥也不输出。
#cat pipe.go
package main
import (
"fmt"
//"time"
)
func main() {
c := make(chan bool, 100)
for i := 0; i < 100; i++ {
go func(i int) {
fmt.Println(i)
c <- true
}(i)
}
for i := 0; i < 100; i++ {
<-c
}
}
这个说是管道要是上万,会耗尽系统管道资源。
#cat waitgroup.go
package main
import (
"fmt"
"sync"
//"time"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go func(i int) {
fmt.Println(i)
wg.Done()
}(i)
}
wg.Wait()
}
这个说是挺好的,因为它用到了原子加减法,这里好像C语言也有类似的函数,
再就是说它是用来阻塞方进程的,WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为n ,Done() 每次把计数器-1 ,wait() 会阻塞代码的运行,直到计数器地值减为0。
这里首先把wg 计数设置为100, 每个for循环运行完毕都把计数器减一,主函数中使用Wait() 一直阻塞,直到wg为零——也就是所有的100个for循环都运行完毕。相对于使用管道来说,WaitGroup 轻巧了许多。
最后,如果要搞裂成函数,得用引用传入,指针变量:
WaitGroup对象不是一个引用类型
WaitGroup对象不是一个引用类型,在通过函数传值的时候需要使用地址:
#cat waitgrouppointer.go
package main
import (
"fmt"
"sync"
//"time"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go f(i, &wg)
}
wg.Wait()
}
// 一定要通过指针传值,不然进程会进入死锁状态
func f(i int, wg *sync.WaitGroup) {
fmt.Println(i)
wg.Done()
}
以上来自:https://blog.csdn.net/u013474436/article/details/88749749
溯源来自:https://mp.weixin.qq.com/s/s9G6yDqfeFepbKT6DJASng
#cat wg.go
package main
import (
"fmt"
"sync"
)
func main() {
ok := true
for i := 0; i <1000; i ++ {
var arr []int
wg := sync.WaitGroup{}
for j := 0; j <2; j ++ {
wg.Add(1)
go func() {
defer wg.Done()
arr = append(arr, i)
}()
}
wg.Wait()
if len(arr) < 2 {
fmt.Printf("error:%d \n", i)
ok = false
break
}
}
if ok {
fmt.Println("ok")
}
}
判断 key 是否在 map 中
var nameList = map[string]string{"姓名": "李四", "性别": "男"}
name, ok := nameList["姓名"] // 假如 key 存在,则 ok = true,否则,ok = false
if ok {
fmt.Println(name)
来自:https://blog.csdn.net/weixin_38168322/article/details/99948042?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control
——————————
#tree -L 2 .|grep go
├── loop.go
├── pipe.go
├── waitgrouppointer.go
└── wg.go
#cat loop.go
package main
import (
"fmt"
//"time"
)
func main(){
for i := 0; i < 100 ; i++{
go fmt.Println(i)
}
//time.Sleep(time.Second)
}
这个说是运行太快,子进程没输出主进程就退了,啥也不输出。
#cat pipe.go
package main
import (
"fmt"
//"time"
)
func main() {
c := make(chan bool, 100)
for i := 0; i < 100; i++ {
go func(i int) {
fmt.Println(i)
c <- true
}(i)
}
for i := 0; i < 100; i++ {
<-c
}
}
这个说是管道要是上万,会耗尽系统管道资源。
#cat waitgroup.go
package main
import (
"fmt"
"sync"
//"time"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go func(i int) {
fmt.Println(i)
wg.Done()
}(i)
}
wg.Wait()
}
这个说是挺好的,因为它用到了原子加减法,这里好像C语言也有类似的函数,
再就是说它是用来阻塞方进程的,WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为n ,Done() 每次把计数器-1 ,wait() 会阻塞代码的运行,直到计数器地值减为0。
这里首先把wg 计数设置为100, 每个for循环运行完毕都把计数器减一,主函数中使用Wait() 一直阻塞,直到wg为零——也就是所有的100个for循环都运行完毕。相对于使用管道来说,WaitGroup 轻巧了许多。
最后,如果要搞裂成函数,得用引用传入,指针变量:
WaitGroup对象不是一个引用类型
WaitGroup对象不是一个引用类型,在通过函数传值的时候需要使用地址:
#cat waitgrouppointer.go
package main
import (
"fmt"
"sync"
//"time"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go f(i, &wg)
}
wg.Wait()
}
// 一定要通过指针传值,不然进程会进入死锁状态
func f(i int, wg *sync.WaitGroup) {
fmt.Println(i)
wg.Done()
}
以上来自:https://blog.csdn.net/u013474436/article/details/88749749
溯源来自:https://mp.weixin.qq.com/s/s9G6yDqfeFepbKT6DJASng
#cat wg.go
package main
import (
"fmt"
"sync"
)
func main() {
ok := true
for i := 0; i <1000; i ++ {
var arr []int
wg := sync.WaitGroup{}
for j := 0; j <2; j ++ {
wg.Add(1)
go func() {
defer wg.Done()
arr = append(arr, i)
}()
}
wg.Wait()
if len(arr) < 2 {
fmt.Printf("error:%d \n", i)
ok = false
break
}
}
if ok {
fmt.Println("ok")
}
}
判断 key 是否在 map 中
var nameList = map[string]string{"姓名": "李四", "性别": "男"}
name, ok := nameList["姓名"] // 假如 key 存在,则 ok = true,否则,ok = false
if ok {
fmt.Println(name)
来自:https://blog.csdn.net/weixin_38168322/article/details/99948042?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/10820/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2021-1-4 19:01
评论列表