January 18, 2020
Golang中关于defer语句理解的一道题
"示例 我们先看一下源代码\npackage main import \u0026#34;fmt\u0026#34; func f(n int) (r int) { defer func() { r += n recover() }() var fc func() defer fc() fc = func() { r += 2 } return n + 1 } func main() { fmt.Println(f(3)) } 大家感觉着打印的值是多少呢?5、9还是7?执行完以后发现是7。好像与多数理解的有些出入,为什么是7,而不是9呢。下面我们来分析一下。\n问题分析 对于defer执行的顺序是FIFO这一点都很清楚,我们只需要看搞懂f()函数的执行顺序就行了。\n执行顺序为:\n注册第1个defer 函数, 这里为匿名函数,函数体为 “func() { r += n recover() }()”,内部对应一个函数指针。这里延时函数所有相关的操作一步完成。 注册第2个defer函数,函数名为fc(),无函数体, 函数指针为nil(也有可能指针不会空,但指针指向的内容非函数体类型)。由于只是注册操作还未执行,所以并 …"
January 15, 2020
开发者必知redis知识点
"剖析Redis常用数据类型对应的数据结构 https://time.geekbang.org/column/article/79159\nredis中的COW(Copy-On-Write) https://www.jianshu.com/p/b2fb2ee5e3a0\nredis常用有哪些数据类型及每种数据类型的使用场景有哪些 https://www.cnblogs.com/tqlin/p/10478459.html\n如果存储一个JSON数据时,选择hash还是string 存储数据? https://segmentfault.com/a/1190000019552836\nredis与memcache的区别 https://www.cnblogs.com/JavaBlackHole/p/7726195.html https://blog.csdn.net/qq_34126805/article/details/81748107\nredis支持多CPU吗?如何发挥多cpu? https://blog.csdn.net/tanga842428/article/details/52641484 …"
January 14, 2020
golang中有关select的几个知识点
"golang中的select语句格式如下\nselect { case \u0026lt;-ch1: // 如果从 ch1 信道成功接收数据,则执行该分支代码 case ch2 \u0026lt;- 1: // 如果成功向 ch2 信道成功发送数据,则执行该分支代码 default: // 如果上面都没有成功,则进入 default 分支处理流程 } 可以看到select的语法结构有点类似于switch,但又有些不同。\nselect里的case后面并不带判断条件,而是一个信道的操作,不同于switch里的case,对于从其它语言转过来的开发者来说有些需要特别注意的地方。\ngolang 的 select 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作每个case语句里必须是一个IO操作,确切的说,应该是一个面向channel的IO操作。\n注:Go 语言的 select 语句借鉴自 Unix 的 select() 函数,在 Unix 中,可以通过调用 select() 函数来监控一系列的文件句柄,一旦其中一个文件句柄发生了 IO 动作,该 select() 调用就会被返回(C 语言中就是这么做的), …"
January 11, 2020
golang中的sync.Pool对象缓存
"参考文章 Golang 的 协程调度机制 与 GOMAXPROCS 性能调优 深入Golang之sync.Pool详解 golang sync.Pool 分析 [译] Go: 理解 Sync.Pool 的设计 视频 sync.pool对象缓存 知识点 Pool只是一个缓存,一个缓存,一个缓存。由于生命周期受GC的影响,一定不要用于数据库连接池这类的应用场景,它只是一个缓存。 golang1.13版本对 Pool 进行了优化,结构体添加了两个字段 victim 和 victimSize。 适应于通过复用,降低复杂对象的创建和GC代价的场景 因为init()的时候会注册一个PoolCleanup函数,他会在gc时清除掉sync.Pool中的所有的缓存的对象。所以每个sync.Pool的生命周期为两次GC中间时段才有效,可以手动进行gc操作 runtime.GC() 由于要保证协程安全,所以会有锁的开销 每个Pool都有一个私有池(协程安全)和共享池(协程不安全),其中私有池只有存放一个值。 每次Get()时会先从当前P的私有池private中获取( 类似MPG模型中的G) 如果获取失败,再 …"
January 11, 2020
golang 的编程模式之“功能选项”
"最近在用go重构iot中的一个服务时,发现库 rocketmq-client-go@v2.0.0-rc1 在初始化消费客户端实现时,实现的极其优雅,代码见 https://github.com/apache/rocketmq-client-go/blob/v2.0.0-rc1/examples/consumer/simple/main.go#L32\nc, _ := rocketmq.NewPushConsumer( consumer.WithGroupName(\u0026#34;testGroup\u0026#34;), consumer.WithNameServer([]string{\u0026#34;127.0.0.1:9876\u0026#34;}), ) err := c.Subscribe(\u0026#34;test\u0026#34;, consumer.MessageSelector{}, func(ctx context.Context, msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) { for i := range msgs { …"
January 4, 2020
MySQL中的 InnoDB Buffer Pool
"一、InnoDB Buffer Pool简介 Buffer Pool是InnoDB引擎内存中的一块区域,主要用来缓存表和索引数据使用。我们知道从内存读取数据要比磁盘读取效率要高的多,这也正是buffer pool发挥的主要作用。一般配置值都比较大,在专用数据库服务器上,大小为物理内存的80%左右。\n二、Buffer Pool LRU 算法 Buffer Pool 链表使用优化改良后LRU(最近最少使用)算法进行管理。\n整个LRU链表可分为两个子链表,一个是New Sublist,也称为Young列表或新生代,另一个是Old Sublist ,称为Old 列表或老生代。每个子链表都有一个Head和Tail,中间部分是存储Page数据的地方。\n当新的Page放入 Buffer Pool 缓存池的时候,会交其Page插入就是两个子链表的交界处,称为midpoint,同时就会有旧的Page被淘汰,整个操作过程都需要对链接进行维护。\nYoung 链表区存放的数据是经常访问的数据; Old 链表区存放是即将被淘汰的数据;\n一个新数据先被插入到midpoint 位置,根据LRU算法访问频率高 …"
December 31, 2019
使用Dockerfile 多阶段构建Golang 应用
"docker在开发和运维中使用的场景越来越多,作为开发人员非常有必要了解一些docker的基本知识,而离我们工作中最近的也就是对应用的docker部署编排了,小到一个dockerfile, docker-compse文件的编写,大到k8s的管理。这里我们以 golang应用为例讲解一些Dockerfile的基本用法,在ci/cd中经常用到这些知识。\n前提 项目清单:\ndrwxr-xr-x 9 sxf staff 288 12 31 16:13 . drwx------@ 17 sxf staff 544 12 31 14:59 .. -rw-r--r-- 1 sxf staff 14 12 31 16:09 .dockerignore drwxr-xr-x 14 sxf staff 448 12 31 16:21 .git -rw-r--r-- 1 sxf staff 467 12 31 16:08 Dockerfile -rw-r--r-- 1 sxf staff 11 12 31 15:01 README.md -rw-r--r-- 1 sxf staff 84 12 31 …"
November 8, 2019
Golang中的goroutine泄漏问题
"goroutine作为Go中开发语言中的一大利器,在高并发中发挥着无法忽略的作用。但东西虽好,真正做到用好还是有一些要注意的地方,特别是对于刚刚接触这门开发语言的新手来说,稍有不慎,就极有可能导致goroutine 泄漏。\n什么是goroutine Leak goroutine leak 的意思是go协程泄漏,那么什么又是协程泄漏呢?我们知道每次使用go关键字开启一个gorountine任务,经过一段时间的运行,最终是会结束,从而进行系统资源的释放回收。而如果由于操作不当导致一些goroutine一直处于阻塞状态或者永远运行中,永远也不会结束,这就必定会一直占用系统资源。最球的情况下是随着系统运行,一直在创建此类goroutine,那么最终结果就是程序崩溃或者系统崩溃。这种情况我们一般称为goroutine leak。\n出现的问题 先看一段代码:\npackage main import ( \u0026#34;fmt\u0026#34; \u0026#34;math/rand\u0026#34; \u0026#34;runtime\u0026#34; \u0026#34;time\u0026#34; ) func query() int { n := …"