rceax.com
Open in
urlscan Pro
172.67.199.14
Public Scan
URL:
https://rceax.com/
Submission: On December 11 via api from US — Scanned from NZ
Submission: On December 11 via api from US — Scanned from NZ
Form analysis
0 forms found in the DOMText Content
編程沉思錄 * 首頁 * Golang源碼剖析 * 分類11 * 歸檔37 * 標簽9 * 開源 * 關於 * 內推 * 搜索 * 文章目錄 * 站點概覽 cyhone 我們采集的隻是石頭,卻必須始終展望著未來的大教堂 掃碼關注公眾號【編程沉思錄】 第一時間收到文章推送 CONTEXT的錯誤使用引發PANIC的問題複盤 發表於 2024-05-06 更新於 2024-05-07 分類於 Golang 閱讀次數: 我們有這麽一段業務代碼,在 Gin 的 API Handler 中,開了一個子 goroutine 寫 DB,代碼大概是這樣: package main import ( "github.com/gin-gonic/gin" "gorm.io/gorm" ) var db *gorm.DB func ServerHandler(c *gin.Context) { // 一些旁路邏輯,為了不影響接口耗時,在子goroutine中執行 go func() { db.WithContext(c).Exec("update xxx") }() // 一些後置邏輯 } 代碼在測試階段一直沒啥問題,但是一上線立馬出現了大麵積的 panic。panic 的棧也非常奇怪,掛在了 mysql driver 裏麵: panic: sync/atomic: store of nil value into Value goroutine 357413 [running]: sync/atomic.(*Value).Store(0xc004097ef0, {0x0,0x0}) /usr/local/go/src/sync/atomic/value.go:47 +0xeb github.com/go-sql-driver/mysql.(*atomicError).Set(..) /root/go/pkg/mod/github.com/go-sql-driver/mysql@v1.6.0/utils.go:831 github.com/go-sql-driver/mysql.(*mysqlConn).cancel(0xc004e6fc20, {0x0, 0x0}) /root/go/pkg/mod/github.com/go-sql-driver/mysql@v1.6.0/connection.go:435 +0x3d github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher.func1() /root/go/pkg/mod/github.com/go-sql-driver/mysql@v1.6.0/connection.go:622 +0x192 created by github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher /root/go/pkg/mod/github.com/go-sql-driver/mysql@v1.6.0/connection.go:611 +0x105 閱讀全文 » GO 1.22 可能將改變 FOR 循環變量的語義 發表於 2023-11-29 分類於 Golang 閱讀次數: 幾乎世界上每個 Golang 程序員都踩過一遍 for 循環變量的坑,而這個坑的解決方案已經作為實驗特性加入到了 Go 1.21 中,並且有望在 Go 1.22 中完全開放。 舉個例子,有這麽段代碼: var ids []*int for i := 0; i < 10; i++ { ids = append(ids, &i) } for _, item := range ids { println(*item) } 可以試著在 playgound 裏麵運行下:go.dev/play/p/O8MVGtueGAf 答案是:打印出來的全是 10。 這個結果實在離譜。原因是因為在目前 Go 的設計中,for 中循環變量的定義是 per loop 而非 per iteration。也就是整個 for 循環期間,變量 i 隻會有一個。以上代碼等價於: var ids []*int var i int for i = 0; i < 10; i++ { ids = append(ids, &i) } 同樣的問題在閉包使用循環變量時也存在,代碼如下: 閱讀全文 » 剖析GOLANG BIGCACHE的極致性能優化 發表於 2023-11-25 更新於 2023-11-28 分類於 Golang 閱讀次數: 本文屬於 《Golang源碼剖析係列》 Bigcache是用Golang實現的本地內存緩存的開源庫,主打的就是可緩存數據量大,查詢速度快。 在其官方的介紹文章《Writing a very fast cache service with millions of entries in Go》一文中,明確提出了bigcache的設計目標: 1. 多: 緩存的元素數量非常大,可以達到百萬級或千萬級。 2. 快: 對延遲有非常高的要求,平均延遲要求在5毫秒以內。redis、memcached之類的就不考慮在內了,畢竟用Redis還要多走一遍網絡IO。 3. 穩: 99.9分位延遲應在10毫秒左右,99.999分位延遲應在400毫秒左右。 目前有許多開源的cache庫,大部分都是基於map實現的,例如go-cache,ttl-cache等。bigcache明確指出,當數據量巨大時,直接基於map實現的cache庫將出現嚴重的性能問題,這也是他們設計了一個全新的cache庫的原因。 本文將通過分析bigcache v3.1.0的源碼,揭秘bigcache如何解決現有map庫的性能缺陷,以極致的性能優化,實現超高性能的緩存庫。 閱讀全文 » 解讀 GOLANG 標準庫裏的 VARINT 實現 發表於 2023-11-23 更新於 2023-11-30 分類於 Golang 閱讀次數: 本文屬於《Golang 源碼剖析係列》。 最近發現 Golang 標準庫竟然自帶了 varint 的實現,代碼位置在 encoding/binary/varint.go,這個跟protobuf裏麵的varint實現基本是一致的。剛好借助 golang 標準庫的 varint 源碼,我們來係統地學習和梳理下 varint。 熟悉 protobuf 的人肯定對 varint 不陌生,protobuf 裏麵除了帶 fix (如 fixed32、fixed64) 之外的整數類型, 都是 varint 編碼。 varint 的出現主要是為了解決兩個問題: 1. 空間效率:以 uint64 類型為例,可以表示的最大值為 18446744073709551615。然而在實際業務場景中,我們通常處理的整數值遠小於 uint64 的最大值。假設在我們的業務中,需要處理的整數值僅為 1,但在網絡傳輸過程中,我們卻需要使用 8 個字節來表示這個值。這就導致了大量的空間浪費,因為大部分字節並沒有實際存儲有效的信息。varint 編碼通過使用可變長度的字節序列來表示整數,使得小的整數可以用更少的字節表示,提高空間效率。 2. 兼容性:varint 使得我們可以在不改變編碼 / 解碼邏輯的情況下,處理不同大小的整數。這意味著我們可以在不破壞向後兼容性的情況下,將一個字段從較小的整數類型(如 uint32)升級到較大的整數類型(如 uint64) 本文將通過分析 Golang 標準庫自帶的 varint 源碼實現,介紹 varint 的設計原理以及Golang標準庫是如何解決 varint 在編碼負數時遇到的問題。 閱讀全文 » 深度分析 GOLANG SYNC.POOL 底層原理 發表於 2021-07-18 更新於 2024-06-07 分類於 Golang 閱讀次數: 本文屬於《Golang 源碼剖析係列》 sync.Pool 是 Golang 內置的對象池技術,可用於緩存臨時對象,以緩解因頻繁建立臨時對象帶來的性能損耗以及對 GC 帶來的壓力。 在許多知名的開源庫中都可以看到 sync.Pool 的大量使用。例如,HTTP 框架 Gin 用 sync.Pool 來複用每個請求都會創建的 gin.Context 對象。 在 grpc-Go、kubernetes 等也都可以看到對 sync.Pool 的身影。 但需要注意的是,sync.Pool 緩存的對象隨時可能被無通知的清除,因此不能將 sync.Pool 用於存儲持久對象的場景。 sync.Pool 作為 goroutine 內置的官方庫,其設計非常精妙。sync.Pool 不僅是並發安全的,而且實現了 lock free,裏麵有許多值得學習的知識點。 本文將基於 go-1.16 的源碼 對 sync.Pool 的底層實現一探究竟。 閱讀全文 » OS.CHMOD 時到底用 777 還是 0777? 發表於 2021-06-20 分類於 Golang 閱讀次數: 問題是這樣的:我在代碼裏麵調用了 os.Chmod("test.txt", 777),希望把該文件的讀寫及執行權限對所有用戶開放。 執行完代碼,順手 ls 看了下。如下: $ ls -l test.txt -r----x--x 1 cyhone 1085706827 0 Jun 20 13:27 test.txt 結果出乎意料,不僅文件權限沒有按預期的變成 rwxrwxrwx。反而執行完後,當前用戶就隻剩可讀權限了,其他用戶就隻有可執行權限同時無讀寫權限。 因為這實在是一個簡單又愚蠢的錯誤,所以先直接給出結論: 1. 在 C 語言和 Go 語言中,如果想要將文件權限形式修改為 rwxrwxrwx,需要寫成 0777,而非 777。 2. 0777 是八進製格式,777 是十進製格式。在用 Go 語言表示此類權限的時候,如果要對標 chmod 命令的表示形式,用八進製表示更方便和準確點。 3. 如果不是在代碼裏,而是在命令行直接調 chmod 的話,那 0777 和 777 都可以。 這個問題雖然非常簡單,但尷尬的是我還踩了坑,所以把這個問題及原因分享出來。 閱讀全文 » 12…7 豫ICP備18011028號 © 2015 – 2024 cyhone 107 107 由 Hexo & NexT.Gemini 強力驅動 Theme NexT works best with JavaScript enabled