成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go編譯時寫入數據的原理

開發 后端
在很多公司甚至開源項目都會采用該方式,在代碼中顯式地添加版本等信息。Go是編譯型語言,版本等信息是否可以在編譯時,自動地打包到二進制文件中?

[[417666]]

場景

公司線上運行的Go服務存在多個版本

時間:某天凌晨

事情:線上Go服務突然間 crash

緊急處理:重啟Go服務

故障排查:查詢日志,找出可能出現的堆棧信息以及追溯源碼

問題:線上同時存在多個版本,如何知道當前 crash 的程序屬于哪個版本?

添加版本信息的兩種方案

方案1,手動添加版本信息:

  1. package main 
  2.  
  3. import ( 
  4.     "flag" 
  5.     "fmt" 
  6. // 下面三個變量,每次發版都要修改 
  7. var version = "v0.0.1" // 程序版本號 
  8. var gitTag = "v0.0.1" // git tag 號 
  9. var dateTime = "2021-08-14 10:00:00" // 編譯生成時間 
  10.  
  11. func main() { 
  12.     debugVerInfo := flag.Bool("ver"false"show app version info"
  13.     flag.Parse() 
  14.  
  15.     if *debugVerInfo { 
  16.         fmt.Println("version is:", version) 
  17.         fmt.Println("dateTime is:", dateTime) 
  18.         fmt.Println("gitTag is:", gitTag) 
  19.         return 
  20.     } 
  21.  
  22.     fmt.Println("do other thing"

由于手動在代碼中添加版本信息,所以在排查時可以查看到對應信息。

  1. ➜  code ✗ ./client -ver   
  2. version is: v0.0.1 
  3. dateTime is: 2021-08-14 10:00:00 
  4. gitTag is: v0.0.1 

分析:

在很多公司甚至開源項目都會采用該方式,在代碼中顯式地添加版本等信息。

  1. 假設不經常發版或者發版周期比較長,則完全沒問題
  2. 假設發版頻繁,很大概率會出現版本信息的遺漏、錯誤
  3. 假設版本信息忘記更改,則查詢出來的信息就是錯的

針對以上情況,提出一個問題:Go是編譯型語言,版本等信息是否可以在編譯時,自動地打包到二進制文件中?

方案2,自動打包版本信息:

  1. package main 
  2.  
  3. import ( 
  4.     "flag" 
  5.     "fmt" 
  6.  
  7. var version = "v0.0.0"// 此處暫時只填寫大的版本號 
  8. var gitTag string 
  9. var dateTime string 
  10.  
  11. func main() { 
  12.     debugVerInfo := flag.Bool("ver"false"show app version info"
  13.     flag.Parse() 
  14.  
  15.     if *debugVerInfo { 
  16.         fmt.Println("version is:", version) 
  17.         fmt.Println("dateTime is:", dateTime) 
  18.         fmt.Println("gitTag is:", gitTag) 
  19.         return 
  20.     } 
  21.  
  22.     fmt.Println("do other thing"

 在編譯時,打包版本等信息到Go的二進制文件中:

  1. go build -ldflags \ 
  2.     "-X main.version=v0.0.1 -X main.dateTime=`date +%Y-%m-%d,%H:%M:%S` -X main.gitTag=`git tag`" \ 
  3.   -o client 

build 通過 -ldflags 的 -X 參數可以在編譯時將值寫入變量

變量格式:包名稱.變量名稱=值

查看版本信息

  1. ➜  code ✗ ./client -ver   
  2. version is: v0.0.1 
  3. dateTime is: 2021-08-14 10:00:00 
  4. gitTag is: v0.0.1 

優點:

無需代碼中顯式添加版本等信息

避免手動添加版本信息時,遺漏或者錯誤等情況發生

可使用持續集成工具自動把版本等信息打包到二進制文件中

原理

二進制文件在加載到內存中之后,整個內存空間會被劃分為若干段。除了代碼區、數據區、堆、棧,還有有一個段為符號表。

在編譯時,把版本等信息打包到符號表中,供程序運行時使用。

  1. [root@localhost demo]# readelf -s client | grep main 
  2.     ...... 
  3.   1686: 00000000005608b0    16 OBJECT  GLOBAL DEFAULT   10 main.version 
  4.   1687: 00000000005608a0    16 OBJECT  GLOBAL DEFAULT   10 main.gitTag 
  5.   1688: 0000000000560890    16 OBJECT  GLOBAL DEFAULT   10 main.dateTime 
  6.     ...... 
  7.   2320: 00000000004eb2e8     7 OBJECT  GLOBAL DEFAULT    2 main.version.str 
  8.   2321: 00000000004ebba0    20 OBJECT  GLOBAL DEFAULT    2 main.dateTime.str 
  9.   2322: 00000000004eb2e0     7 OBJECT  GLOBAL DEFAULT    2 main.gitTag.str 

使用 readelf -s命令查看編譯好的Go二進制文件符號表信息,可以明顯看到在編譯時寫入的三個變量。

其中,main.version、main.gitTag、main.dateTime 大小都為16,是指 在Go中的string類型結構體大小。

  1. (gdb) ptype version 
  2. type = struct string { 
  3.     uint8 *str; 
  4.     int len; 
  5.  
  6. (gdb) ptype dateTime 
  7. type = struct string { 
  8.     uint8 *str; 
  9.     int len; 
  10.  
  11. (gdb) ptype gitTag 
  12. type = struct string { 
  13.     uint8 *str; 
  14.     int len; 

不知細心的你是否發現,在符號表顯示的變量具體值 main.version.str、main.dateTime.str、main.gitTag.str長度都比實際多一個字節。

雖然目前Go實現了自舉,但是編譯Go編譯器的編譯器還是用C語言寫的

C語言字符串(字節數組)是非安全類型,使用尾零來標識字符串結束。其中,尾零也占用一個字節。

尾零是 ASCII 第一個元素 0, 即:NUL

  1. (gdb) p version 
  2. $1 = "v0.0.1" 
  3.  
  4. (gdb) p dateTime 
  5. $2 = "2021-08-13,23:26:44" 
  6.  
  7. (gdb) p gitTag 
  8. $3 = "v0.0.1" 

 

責任編輯:姜華 來源: 今日頭條
相關推薦

2020-09-14 08:56:30

Vue模板

2024-11-15 09:54:58

2023-05-08 08:05:42

內核模塊Linux

2017-04-11 08:36:09

iOS編譯應用

2021-10-26 13:18:52

Go底層函數

2019-12-06 13:59:37

代碼開發Python

2010-01-15 10:16:50

CentOS rpm安

2022-12-30 20:41:15

編譯原理case

2021-05-13 18:53:34

Go編譯器Uber

2013-12-30 11:21:31

Go編譯器

2023-12-25 07:46:01

Go語言循環

2021-10-20 06:47:50

Elasticsear場景引擎

2021-07-28 07:53:21

Go語言拷貝

2017-05-26 11:07:17

Android框架代碼

2021-03-16 08:56:35

Go interface面試

2021-08-02 15:02:37

Go Excelize 開發

2023-03-09 11:32:00

MongoDB數據策略

2024-10-16 09:57:52

空結構體map屬性

2021-06-07 23:51:16

MacGo服務

2022-10-24 00:48:58

Go語言errgroup
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久久久久久 | 人人爽日日躁夜夜躁尤物 | 亚洲欧洲中文 | 日韩精品一区二区三区中文在线 | 欧美日韩国产一区二区三区 | 91影院在线观看 | 亚洲国产精品久久 | 欧美日韩亚洲国产 | 久久精品国产免费一区二区三区 | 久久精品二区亚洲w码 | 国产伦精品一区二区三区高清 | 精品一区二区三区四区外站 | 天天干精品 | 亚洲成人黄色 | 亚洲精品视频在线看 | 久精品久久 | 99视频 | 免费久久99精品国产婷婷六月 | 日韩一区二区三区在线 | 99久久亚洲 | 在线亚洲免费视频 | 青青草社区 | 国产精品视频一区二区三区四区国 | 中文字幕一区二区三区不卡 | 激情久久网 | 国产永久免费 | 熟女毛片 | 国产1区| 亚洲国产精品久久 | 成人精品一区二区 | 中文字幕精品一区久久久久 | 久久久国产一区二区三区 | 激情毛片 | 久久久久久九九九九 | 视频一区二区在线观看 | 91xxx在线观看 | 91av大全| 岛国在线免费观看 | 国产视频一区二区 | 国产色婷婷久久99精品91 | 色伊人久久 |