Go语言爱好者周刊:第 70 期

polaris · 2020-11-22 00:25:33 · 8307 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2020-11-22 00:25:33 的主题,其中的信息可能已经有所发展或是发生改变。

这里记录每周值得分享的 Go 语言相关内容,周日发布。

本周刊开源(GitHub:polaris1119/golangweekly),欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue

鉴于大部分人可能没法坚持把英文文章看完,因此,周刊中会尽可能推荐优质的中文文章。优秀的英文文章,我们的 GCTT 组织会进行翻译。

题图:golangweekly

刊首语

一道问答题:以下代码可能有什么问题?如何改进?

type Stats struct {
    mutex sync.Mutex

    counters map[string]int
}

func (s *Stats) Snapshot() map[string]int {
    s.mutex.Lock()
    defer s.mutex.Unlock()

    return s.counters
}

func (s *Stats) Add(name string, num int) {
    s.mutex.Lock()
    defer s.mutex.Unlock()
    s.counters[name] = num
}

欢迎留言讨论。

资讯

1、Go 标准库性能测试,对比 Intel 和 苹果 M1 处理器

想知道基于 Apple M1 的笔记本电脑与基于 Intel 的笔记本电脑的 Go 性能如何?这个测试可以看看。

2、GoLand 2020.3 Beta 版发布

与“抢先体验计划”版本相比,该测试版非常稳定,但是请记住,这里和那里仍然可能存在一些粗糙的地方。

3、GitHub 向开发着妥协,恢复 youtube-dl 项目

下载用。

文章

1、一起看看 Go1.14 的抢占调度

抢占是调度器的重要部分,基于抢占调度器可以在各个协程中分配运行的时间。

2、Go 最细节篇 — chan 为啥没有判断 close 的接口 ?

相信大家初学 golang chan 的时候应该都遇到过 "send on closed channel" 的 panic 。

3、通过这个 Runtime 统计信息可视化库学到了什么?

掌握系统运行状态,知道系统哪些地方可能存在问题,方便进行优化,这是一个实际系统必备的。裸奔,对系统一无所知,迟早是要出大事的。

4、C++ 调用 Go 方法的字符串传递问题及解决方案

C++ 调用 Go 方法时,字符串参数的内存管理需要由 Go 侧进行深度值拷贝。

5、聊聊 Go 和创业

PingCAP、七牛、掘金。。。

6、Go 语言名人:除了 Rob Pike,很多人可能不知道他

Russ Cox 是 Go Team Leader。

7、在 Go 中恰到好处的内存对齐

通过本文的介绍,可得知是由于不同类型导致需要进行字节对齐,以此保证内存的访问边界。

8、Go 基准测试还可以这么搞?高级基准测试

有时你必须解决不同类型的问题。通常来说复杂的问题并不会只有单一的解决方案,但是解决方案的优劣取决于程序在运行时所要解决问题的子集。

9、Go 语言之 pprof 的性能调优 “燥起来”

在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况。 Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling 的库,这篇文章就要讲解怎么在 golang 中做 profiling。

10、Golang 协程并发的流水线模型

总结下 golang 协程并发常用的流水线模型。

11、好未来开源框架 go-zero:如何用它进行 rest 开发?

go-zero 是一个集成了各种工程实践的 web 和 rpc 框架,其中 rest 是 web 框架模块,基于 Go 语言原生的 http 包进行构建,是一个轻量的,高性能的,功能完整的,简单易用的 web 框架。

12、为什么 Go 的泛型一拖再拖?

据说 2022 年 2 月会有泛型。

13、Java 微服务能像 Go 一样快吗?

留言比较有料。

开源项目

1、gomponents

Go 中的声明式视图组件,可以呈现为 HTML5。

2、address

地址处理库,支持多国语言。

3、peer-calls

为使用 Go 和 TypeScript 编写的进行点对点视频通话。

4、ebpf

eBPF 是一个纯 Go 库,提供用于加载,编译和调试 eBPF 程序的实用程序。它具有最小的外部依赖性,适合在长时间运行的进程中使用。

5、h2go

Apache H2 Go SQL Driver。

6、statsview

实时 Golang 运行时统计数据可视化分析器。

7、k0s

最小体积的发行版 k8s。

8、gwda

用 Golang 实现 appium/WebDriverAgent 的客户端库,使得 Gopher 也可以编写代码来控制 iOS iPadOS 设备的各种操作。

资源&&工具

1、go-getter

可使用 URL 作为输入的主要形式从各种来源下载文件或目录。

2、gdriver

从 Google Drive 下大文件。

3、油管视频

深入 go build cache。

4、适合 Go 新手学习的开源项目

看看有没有你需要的。

5、rf

Go 重构工具,目前还是实验阶段。

订阅

这个周刊每周日发布,同步更新在Go语言中文网微信公众号

微信搜索"Go语言中文网"或者扫描二维码,即可订阅。

wechat


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

8307 次点击  
加入收藏 微博
15 回复  |  直到 2020-11-24 09:34:27
golang_007
golang_007 · #1 · 4年之前

s.Lock 是什么? Snapshot 暴露了内部map,依旧会有并发写问题

6133302
6133302 · #2 · 4年之前
golang_007golang_007 #1 回复

s.Lock 是什么? Snapshot 暴露了内部map,依旧会有并发写问题

点赞

little_rain
little_rain · #3 · 4年之前

Snapshot相当于读,add相当于写,例子实现了,读读互斥,写写互斥。但是,仍然可以在频繁写的情况下,读。所以数据竞态依然存在。改成读写锁,Snapshot用读锁,add用写锁,可以解决读写的数据竞态。对不对?

GotoLove-LoonGL
GotoLove-LoonGL · #4 · 4年之前

发现微信上的消息没有同步到这边

GotoLove-LoonGL
GotoLove-LoonGL · #5 · 4年之前

还是请大佬来个系统性的回答吧@站主

focusonline
focusonline · #6 · 4年之前

对于map这种结构来说 不用深拷贝做snopshot是没用的.直接返回是一个浅拷贝,加了锁卵用没有. go语言没有泛型真的是太遗憾了, 如果有泛型 不需要面对对象用来写业务就会犀利很多. 现在还是比较麻烦, 虽然用熟悉了写起来也不慢只是代码美观和精炼上就不行了.

polaris
polaris · #7 · 4年之前

还是请大佬来个系统性的回答吧@站主

这里的关键在于 map 是引用类型,Snapshot 内部好像加锁了,其实没用。这么改一下才正确,大家应该明白怎么回事:

func (s *Stats) Snapshot() map[string]int {
  s.mutex.Lock()
  defer s.mutex.Unlock()

  result := make(map[string]int, len(s.counters))
  for k, v := range s.counters {
    result[k] = v
  }
  return result
}
focusonline
focusonline · #8 · 4年之前

本文的配图太招人喜欢了. 果断下载收藏

GotoLove-LoonGL
GotoLove-LoonGL · #9 · 4年之前
polarispolaris #7 回复

#5楼 @GotoLove-LoonGL 这里的关键在于 map 是引用类型,Snapshot 内部好像加锁了,其实没用。这么改一下才正确,大家应该明白怎么回事: ```go func (s *Stats) Snapshot() map[string]int { s.mutex.Lock() defer s.mutex.Unlock() result := make(map[string]int, len(s.counters)) for k, v := range s.counters { result[k] = v } return result } ```

只有这一个问题吗?看大家讨论的方法还挺多,我去群里问问大佬们怎么看

GotoLove-LoonGL
GotoLove-LoonGL · #10 · 4年之前
golang_007golang_007 #1 回复

s.Lock 是什么? Snapshot 暴露了内部map,依旧会有并发写问题

是不是在读的时候上锁了,但是在其他地方在写,然后还是有可能读出来的内容改变

little_rain
little_rain · #11 · 4年之前
polarispolaris #7 回复

#5楼 @GotoLove-LoonGL 这里的关键在于 map 是引用类型,Snapshot 内部好像加锁了,其实没用。这么改一下才正确,大家应该明白怎么回事: ```go func (s *Stats) Snapshot() map[string]int { s.mutex.Lock() defer s.mutex.Unlock() result := make(map[string]int, len(s.counters)) for k, v := range s.counters { result[k] = v } return result } ```

懂了,Snapshot应该返回拷贝,而不是返回本身的map。

little_rain
little_rain · #12 · 4年之前

#1楼 @golang_007 是不是在读的时候上锁了,但是在其他地方在写,然后还是有可能读出来的内容改变

snapshot的问题应该主要还是返回的错误,返回的应该是counters的一个拷贝,而不是它自身。如果是返回它自身,那么任何人都可以操作这个map了。如果返回counters的拷贝,则不会影响到本身的counters。

GotoLove-LoonGL
GotoLove-LoonGL · #13 · 4年之前
little_rainlittle_rain #12 回复

#10楼 @GotoLove-LoonGL snapshot的问题应该主要还是返回的错误,返回的应该是counters的一个拷贝,而不是它自身。如果是返回它自身,那么任何人都可以操作这个map了。如果返回counters的拷贝,则不会影响到本身的counters。

懂了,但是为什么有些人说不应该用互斥锁,应该用读写锁,我不是很理解

little_rain
little_rain · #14 · 4年之前
little_rainlittle_rain #3 回复

Snapshot相当于读,add相当于写,例子实现了,读读互斥,写写互斥。但是,仍然可以在频繁写的情况下,读。所以数据竞态依然存在。改成读写锁,Snapshot用读锁,add用写锁,可以解决读写的数据竞态。对不对?

1

little_rain
little_rain · #15 · 4年之前

#12楼 @little_rain 懂了,但是为什么有些人说不应该用互斥锁,应该用读写锁,我不是很理解

我理解的问题,我记得书上说过数据竞态,如果操作一个很大的数据,比如增加,数据很大的话,还没加完,加到一半,就被读出去了,这时数据就不准确了,谁也不知道读出是多少。加了互斥锁,应该就能解决这个问题了。我多虑了。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传