V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  grzhan  ›  全部回复第 4 页 / 共 23 页
回复总数  441
1  2  3  4  5  6  7  8  9  10 ... 23  
2024-11-14 18:10:10 +08:00
回复了 IIInsomnia 创建的主题 Go 编程语言 从 0 到 1 手撸一个协程池
感觉控制协程数量的场景属于内部造轮子可以解决的轻量需求,如果是我的话大概率也是自己造轮子来定制(参考开源实现)而不是引入第三方依赖。
2024-11-13 10:48:17 +08:00
回复了 Charlie17Li 创建的主题 Go 编程语言 [golang 语言] 为啥在 golang 中不支持将 bool 强转成 int?
发现自己贴错了 issue: https://github.com/golang/go/issues/64825 ( x
这个讨论还提到一个点,就是常量,现在常量由于这个类型转换的限制可能对于同个常量会写两个类型( bool/int ),这在 Go 编译器和运行时的代码里就有出现( src/internal/goexperiment/exp_arenas_on.go ):

const Arenas = true
const ArenasInt = 1

总之这事目前来看没有明确拒绝的理由,更接近于懒得搞,如果有人愿意费力气把这变更做了,感觉 Go 团队这边也会接受。

(其实这种类似的情况在 Go 社区有很多,习惯就好)
2024-11-12 22:44:52 +08:00
回复了 Charlie17Li 创建的主题 Go 编程语言 [golang 语言] 为啥在 golang 中不支持将 bool 强转成 int?
我翻了下 Go 的 Github Issue ,其实有非常多人的提过这个 int(bool) proposal 。
包括今年也有关于这个的讨论: https://github.com/golang/go/issues/6011

看得出来不少 Go 团队的成员是支持加入这个特性的,主要反对的人是 rsc ,他认为这个变更工作量很大,同时觉得收益不高,Go 团队时间有限,要搞的话你们自己搞:1. spec 的变更; 2. 编译器和 go/types 的变更; 3. 把 Go 主仓库相关代码更新了以尽可能用上这个新特性,来证明这个特性对于 Go 而言是有用的。

所以感觉更接近 Go 早期版本忽视了这个特性,然后现在随着 Go 发展要加进这个特性工作量大了就懒得搞了。
2024-11-12 16:41:40 +08:00
回复了 winglechen 创建的主题 程序员 写本技术书,能不能熬过这个内卷时代。
draveness 大佬的《 Go 语言设计与实现》我之前一直看: https://draveness.me/golang/
他应该就是先写系列文章( gitbook ),在收获比较高的访问量与关注度之后,出版了实体书。
我觉得是个路子,然后像 draveness 会画很多配图(确定好配色后用 sketch 画),对于这种源码分析读物的可读性提升了很多,但也更费功夫。
供参考。
2024-11-10 21:42:20 +08:00
回复了 xoxo419 创建的主题 程序员 你见过哪些好玩又花里胡哨的代码呢
Golang 标准库 sys.TrailingZeros64
通过 deBruijn 序列快速计算一个 64 位二进制末尾有多少个 0:

var deBruijn64tab = [64]byte{
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
}

const deBruijn64 = 0x03f79d71b4ca8b09

// TrailingZeros64 returns the number of trailing zero bits in x; the result is 64 for x == 0.
func TrailingZeros64(x uint64) int {
if x == 0 {
return 64
}
// If popcount is fast, replace code below with return popcount(^x & (x - 1)).
//
// x & -x leaves only the right-most bit set in the word. Let k be the
// index of that bit. Since only a single bit is set, the value is two
// to the power of k. Multiplying by a power of two is equivalent to
// left shifting, in this case by k bits. The de Bruijn (64 bit) constant
// is such that all six bit, consecutive substrings are distinct.
// Therefore, if we have a left shifted version of this constant we can
// find by how many bits it was shifted by looking at which six bit
// substring ended up at the top of the word.
// (Knuth, volume 4, section 7.3.1)
return int(deBruijn64tab[(x&-x)*deBruijn64>>(64-6)])
}


-------

1. (x & -x) 会把 x 除了最低位以外的 1 都清 0
2. deBrujin64 是一个德布鲁因数,它有个重要性质:它相当于一个循环的德布鲁因序列,每个长度为 6 的二进制子串在里面恰好出现一次,也就是说这个德布鲁因数包含所有的 6 位二进制数,且通过不同次数的位移可以恰好得到。
3. x 若有 k 个 0 , 那么 (x & -x) * deBrujin64 就相当于 deBrujin64 << k ,注意左移是会回绕的,因此 (deBrujin64 << k) >> 58 可以恰好得到 k 在 deBrujin64 中对应的六位唯一二进制子序列
4. deBrujin64tab 就是 k 与对应六位二进制子序列(数)的映射,因此可以快速找到对应的 k ,也就是末尾多少个 0

据说该方法来自 Knuth 的 The Art of Computer Programming 7.3.1 ,回头找一下再学习下。

sys.TrailingZeros64 的性能在很多 Go 运行时场景都至关重要,Golang 有很多 free-list allocator ,比如 mspan 就会用 allocCache bitmap 位图来快速定位可以分配的 free object ,所以计算这个 bitmap 末尾有多少个 0 ,就能快速找到可以被重复利用分配的 free object
2024-11-05 00:32:38 +08:00
回复了 yujianwjj 创建的主题 Go 编程语言 golang 中使用继承的一个疑惑:子类对象赋值给父类
其实 Golang 的 Embedding (嵌入) 也很灵活,因为嵌入不光能够嵌入 struct ,还能嵌入 interface 。

经典的实现是标准库 context ,比如实现 context.WithCancel 的关键结构体 cancelCtx ,就是嵌入了接口 Context ,当 cancelCtx 初始化时,会把 parent 塞给 cancelCtx.Context ,关键在于由于 cancelCtx.Context 是个接口,所以你可以把任意实现了 Context 接口的类型作为 parent 塞给 cancelCtx ,以此实现一种“继承”。

cancelCtx 源码:
https://github.com/golang/go/blob/76f3e0ac8d094b2bc5f8a3fb8a19d1d17a07fe2c/src/context/context.go#L423

这就是为什么不同的 context 底层结构体( cancelCtx 、timerCtx 、valueCtx……)可以通过 WithCancel 、WithDeadline 、WithValue 等标准库方法组成一个灵活的“context 链”, 还能够基于拼接顺序 "override" 各自的实现方法,第一次看源码的时候觉得还是挺奇妙的。

所以当你有扩展行为实现的需求的时候,在 Go 确实要首先考虑用接口
2024-11-04 23:39:48 +08:00
回复了 rainbowStay 创建的主题 Go 编程语言 关于 sync.Map 的一点疑问
这里 iface 写错了,interface{} 应该是对应 eface
2024-11-04 23:35:07 +08:00
回复了 rainbowStay 创建的主题 Go 编程语言 关于 sync.Map 的一点疑问
关键在于 Sync.Map.Store(k, v) ,当你传值为 nil 调用 Store 时,因为 k,v 的类型是 any (也就是 interface{}),在 runtime 也就是结构体 iface ,如果你传入的是 nil ,golang 会用 iface 把这个 nil 包一下,对应的 _type 与 data 应该都是空值(nil),所以你可以在 sync.Map.Store 里面后续的源码里可以看到,value 是可以拿到内存地址的(&value ),因为这个 value 本质上是个 iface 结构体,而直接写 &nil 在 Golang 是会编译报错的。

而 readOnly.m 的值类型是 entry ,entry.p 是一个指向 interface{} 值的指针。当你调用 Sync.Map.Store(k, nil) 时,对应的 entry.p 不会变成 nil ,而是变成一个指向 interface{} (iface) 的指针,这个 iface 相当于包装了值 nil 。

而 Sync.Map.Delete() 就确实会把 entry.p 变成 nil ,所以二者确实是有明确区别的。

写一个函数就可以简单验证,也可以汇编拿出来自己看下:

package main

import "fmt"

func printAnyAddr(v any) {
fmt.Println(&v)
}

func main() {
printAnyAddr(nil)
}
看 go runtime 和 go 标准库的源码能够快速提升 Go 语言的基础理解,而且能学习一套可能是 Go 团队比较中意的实践代码风格(其实很像 C )。

《 Go 语言设计与实现》 - https://draveness.me/golang/
golang-note - https://github.com/cch123/golang-notes/tree/master

这是 Go 语言设计实现源码分析的系列文章可以看下,注意下文章里对应的 Go 版本可能比较老了。不过关于 Go 的 GC 这两个项目没有讲得很全面,要看的话估计还得再找找。

Go 语言是自举的,所以通过学习 Go 语言本身的源码确实提升很快。

K8S 的源码我个人感觉其实风格不是很 Go ,即便用 Java 重新写一套感觉也没啥违和感。我自己最近在看 VictoriaMetrics , 作者应该算是 Go 性能大师了,可以学到很多内存管理、并发控制、IO 优化的内容,里面也包括一些他自己写的轮子:fastcache 、uint64set 等等,都是挺值得琢磨的,欢迎讨论。

看完 VM 以及作者的其他项目(如 fasthttp )我可能会去看 NATS ,因为作为 Go 实现的消息队列它已经实现了很多对标 Kafka 的功能,所以也看看设计,以及思考性能上有没有优化空间。
2024-10-30 14:26:14 +08:00
回复了 RoccoShi 创建的主题 Go 编程语言 新手问一个 go 实现并发素数筛的问题
说起来这个 Rob Pike 的素数筛法应该思路就是当年 CSP 1978 这篇论文提到的素数算法,以前欧长坤老板做过 CSP 1978 论文解读的分享,里面就有素数筛法的例子,论文当然是自己的 CSP 语言,而他写了个 Go 版本:
https://github.com/changkun/pkg/blob/f787593b4467793f8ee0b07583ea9ffde5adf2be/csp/csp.go#L833
2024-10-30 04:03:55 +08:00
回复了 RoccoShi 创建的主题 Go 编程语言 新手问一个 go 实现并发素数筛的问题
这应该单纯是个闭包问题:

1. ch 变量本质上是个 *hchan ( https://github.com/golang/go/blob/ed035af7b7d7c1cd2e6f852e22a9b04fc2a2cc65/src/runtime/chan.go#L34 ),是指向 make(chan int) 也就是 runtime.makechan 创建的 hchan 的指针。

2. 直接使用闭包引用 ch ,ch 发生了内存逃逸(因为是 go func ,我 -gcflags="-m" 看了下确实逃逸到了堆),你在闭包 go func 中使用 ch ,就是在操作 ch 指向的 hchan 。

3. main 函数后续 ch = ch1 , 也就是 ch 指向了原本 ch1 指向的 hchan ,导致 go func 操作的 hchan 也发生了变化,进而整体程序没有按照预期执行。

4. 而正确的实现 Generate(ch),以及 func(ch){...}(ch) ,是函数传参,是将 ch 变量值复制传入到了 Generate 或者 go func 里。

如果你去看汇编,这次 ch 就分配在栈里( main.ch+40(SP) ),在运行 go func 之前就把它的值复制到寄存器里供函数使用了 ( MOVQ main.ch+40(SP), CX )。因此后续 main 里 ch 针对 hchan 的指向发生变化不会影响 go func 内部,值复制保证 go func 内部指向的 hchan 不变。


感兴趣自己可以看下汇编研究下,我也只是大致看了下:go tool compile -S main.go > assembly.s
2024-10-28 14:13:38 +08:00
回复了 florentino 创建的主题 Go 编程语言 使用 golang 可以开发一套监控系统吗
看需求更接近开发一个上报监控指标的 agent ,逻辑上应该比较简单。
解决资源问题(内存)可以看下 tinygo ,算是针对嵌入式环境的一个 go 编译器实现,如果没有用不到 go 关键字、反射等特性的话应该问题不大。
中午饭吃饱,下午喝些茶、咖啡,或者水
感觉大的可能的收益是在二进制序列化协议( protobuf ),一般外部接口感觉是在传输 payload 比较大的时候可能会考虑使用,类似 Prometheus Remote Write API , 一次请求可能是几 MB 或者几十 MB 的写入,Protobuf + Snappy 压缩,也可以像 VictoriaMetrics 使用 zstd 进行压缩,当然传输协议其实还是 HTTP 。

我不是做移动端的,看了下 Android 的文档也确实有 gRPC 方案的文档介绍( https://developer.android.com/guide/topics/connectivity/grpc ),但也不是主推的样子。加上上面很多老板提到的调试成本、学习门槛,以及弱网下 grpc 可能会存在坑,导致看下来 grpc 在客户端通信通用场景的优势并不明显。
2024-10-24 22:44:45 +08:00
回复了 kneo 创建的主题 程序员 急需一个久坐监控
和楼上说的差不多。

MediaPipe 有 Google 开箱即用的人脸识别方案:
https://ai.google.dev/edge/mediapipe/solutions/vision/face_detector?hl=zh-cn
https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker/web_js?hl=zh-cn

然后你检测摄像头有人脸(或者划定一个关注识别的 rect 里面有人脸的话,基于识别到的特征点来判定)就认为你坐着,然后过几十分钟就弹出来提示。
2024-10-24 21:10:21 +08:00
回复了 pengtao2001 创建的主题 程序员 大佬们,如何看源码啊?
另外工具的话一般我就用 jetbrains 全家桶,开箱即用,Ctrl+B 下钻函数,Alt+F7 查某个对象某个函数在哪些地方被使用了,Ctrl+Alt+左方向 上翻自己上一个跳转,Ctrl+Alt+右方向 下翻自己下一个跳转,Shift+Shift+Shift 全局搜索,这些基本够用了也挺好用的。
2024-10-24 21:07:08 +08:00
回复了 pengtao2001 创建的主题 程序员 大佬们,如何看源码啊?
我看代码都是记笔记的,而且是手写书面笔记(可能 ipad pro 记笔记也不错?)比如一个章节就是介绍某个函数或者某个类的,这个函数分成几个部分,又调用了哪几个函数,然后下钻的函数再分别记笔记……

如果理解的部分就不需要抄代码直接用自然语言描述下,不理解的部分就标注待后面回过头看,或者查资料( gpt 、源码分析)来综合理解。

手写笔记有个好处可以翻到前面去和当前下钻的函数和新理解的代码做对照,可能之前不理解的部分看到后面结合一下一下子就理解了。

看完一个部分后可能会找网上的源码分析进行对照,看看自己还有没有什么疏漏的地方。

不记笔记的话还有种办法就是写博客,自己从头介绍一个功能、一个模块的源码分析,这样实际写博客要讲给别人的时候就会知道哪些概念自己还不明白。

当然这些都算是笨办法,效率不是很高,但从结果上来说是让我可以理解、看得进去代码的,而且这也是个热身的过程,随着对于代码理解得越深,很多笔记就会越简略。
1  2  3  4  5  6  7  8  9  10 ... 23  
关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   871 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 29ms · UTC 22:27 · PVG 06:27 · LAX 14:27 · JFK 17:27
♥ Do have faith in what you're doing.