本文目錄一覽:
- 1、golang cgo 怎麼傳字元串
- 2、Golang高效地拷貝big.Int
- 3、Golang複製結構體
- 4、golang unicode/utf8源碼分析
- 5、請Golang深度用戶說說,現在Golang的性能可以和C比嗎
- 6、【golang】小技巧-利用io.copy寫數據進文件
golang cgo 怎麼傳字元串
第一步:all.bash
% cd $GOROOT/src
% ./all.bash
第一步有些突兀,因為 all.bash 僅僅調用了其它兩個 shell 腳本;make.bash 和 run.bash。如果你在使用 Windows 或 Plan 9,過程是一樣的,只是腳本擴展名變成了.bat 或.rc。對於本文中的其它腳本,請根據你的系統適當改動。
第二步:make.bash
. ./make.bash –no-banner
main.bash 來源於 all.bash,因此調用退出將正確終止便宜進程。main.bash 有三個主要工作,第一個是驗證編譯 Go 的環境是否完整。完整性檢查在過去幾年中建立,它通常嘗試避免使用已知的破損工具或必然失敗的環境進行編譯。
第三步. cmd/dist
gcc -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist cmd/dist/*.c
一旦可用性檢查完畢,make.bash 將編譯產生 cmd/dist,cmd/dist取代了之前存在於Go 1 之前的Makefile 編譯系統。cmd/dist用來管理少量的pkg/runtime的代碼生成。cmd/dist 是C語言編寫的程序,能夠充分利用系統C編譯器和頭文件來處理大部分主機系統平台的檢測。cmd/dist通常用來檢測主機的操作系統和體系結構,即環境變數$GOHOSTOS和$GOHOSTARCH .如果是交叉編譯的話,變數 $GOOS和$GOARCH可能會由於你的設置而不同。事實上,Go 通常用作跨平台編譯器,只不過多數情況下,主機和目標系統一致而已。接下來,make.bash 調用cmd/dist 的引導參數的支持庫、 lib9、 libbio 和 libmach,使用編譯器套件,然後用自己的編譯器進行編譯。這些工具也是用 C 語言寫的中,但是由系統 C 編譯器編譯產生。
echo “# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH.”
buildall=”-a”
if [ “$1” = “–no-clean” ]; then
buildall=””
fi
./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
使用的編譯器套件 cmd/dist 編譯產生一個版本的gotool,go_bootstrap。但go_bootstrap並不是完整得gotool,比方說 pkg/net 就是孤立的,避免了依賴於 cgo。要編譯的文件的列表以及它們的依賴項,是由cmd/dist編譯的 ,所以十分謹慎地避免引入新的生成依賴項 到 cmd/go。
第四步:go_bootstrap
現在, go_bootstrap 編譯完成了,make.bash 的最後一部就是使用 go_bootstrap 完成 Go 標準庫的編譯,包括整套 gotool 的替換版。
echo “# Building packages and commands for $GOOS/$GOARCH.”
“$GOTOOLDIR”/go_bootstrap install -gcflags “$GO_GCFLAGS” \
-ldflags “$GO_LDFLAGS” -v std
第五步:run.bash
現在,make.bash 完成了,運行回到了 all.bash,它將引用 run.bash。run.bash 的工作是編譯和測試標準庫,運行時以及語言測試套件。
Golang高效地拷貝big.Int
試圖通過拷貝 *big.Int 指針所指的結構:
這種方式是錯誤的,因為 big.Int 結構內部有 slice ,拷貝結構的話內部的 slice 仍然是共享內存。
點擊運行測試
思想:
思想:
copier 內部實現使用了 reflect 。
思想
Benchmark測試
big.Int = 10
big.Int = 100000000222222222222222222220000000000000000000
比較兩次運行的結果,發現:
+ 0 是最好的選擇
Golang複製結構體
Golang中複製結構體,可以使用賦值語句
執行結果
可以看出,roger跟mydog在內存中的地址不同。並且對mydog修改屬性,對roger沒有影響。
但是注意,這裡的Dog結構體中的屬性,都是值類型。如果是 引用類型 的話,複製的是 指針 ,而不是具體的值。所以通過賦值語句對結構體的拷貝,是 淺拷貝 。如需對引用類型屬性進行深拷貝,可以通過手動創建的方式,或者使用實現了deepcopy功能的第三方包
golang unicode/utf8源碼分析
包 utf-8 實現的功能和常量用於文章utf8編碼,包含runes和utf8位元組序列的轉換功能.在unicode中,一個中文佔兩個位元組,utf-8中一個中文佔三個位元組,golang默認的編碼是utf-8編碼,因此默認一個中文佔三個位元組,但是golang中的字元串底層實際上是一個byte數組.
Output:
RuneSelf該值的位元組碼值為128,在判斷是否是常規的ascii碼是使用。hicb位元組碼值為191. FF 的對應的位元組碼為255。
計算字元串中的rune數量,原理:首先取出字元串的碼值,然後判斷是不是個小於128的,如果是小於則直接continue.rune個數++.
如果是個十六進位f1.的則是無效字元,直接continue.rune個數++,也就是說一個無效的字元也當成一個字長為1的rune.如果字元的碼值在first列表中的值和7按位的結果為其字長,比如上面示例中的 鋼 。其字長為三位,第一位的值為 233 .二進位形式為 11101001 ;與7按位與後的值為0.從acceptRanges中取出的結果為{locb, hicb}。也就是標識 ox80 到 0xbf 之間的值。而結果n也就是直接size+3跳過3個位元組後,rune個數++。其他函數的處理流程差不多,不再過多敘述。
示例:
ValidString返回值表明參數字元串是否是一個合法的可utf8編碼的字元串。
RuneCount返回參數中包含的rune數量,第一個例子中將 utf8.RuneCountInString ,改成該方法調用,返回的結果相同。錯誤的和短的被當成一個長一位元組的rune.單個字元 H 就表示一個長度為1位元組的rune.
該函數標識參數是否以一個可編碼的rune開頭,上面的例子中,因為字元串是以一個ascii碼值在0-127內的字元開頭,所以在執行
first[p[0]] 時,取到的是 p[0] 是72,在first列表中,127之前的值都相同都為 0xF0 ,十進位標識為240,與7按位與後值為0,所以,直接返回 true .
和FullRune類似,只是參數為字元串形式
請Golang深度用戶說說,現在Golang的性能可以和C比嗎
不可以,完全沒有可比性。
Golang的優勢是開發速度,C可以自由、精準的操控內存。
拿string類型舉個栗子:
1、修改字元串:
golang:需要分配新內存,然後進行內存copy。
c:可直接修改,可realloc。
2、存一段data:
golang:使用[]byte類型,[]byte轉成string需要進行內存拷貝(排除掉利用指針進行類型轉換的情況)。
c:直接用char[],可讀可寫。
golang中為了語言的安全性,類似的這種限制有很多,犧牲了一部分性能。但golang的優勢也是顯而易見的,goroutine、chan都很好用,而c則需要自己進行進程、線程的管控。
【golang】小技巧-利用io.copy寫數據進文件
io.copy是按默認的緩衝區32k循環操作的,不會將內容一次性全寫入內存中,這樣就能解決大文件的問題。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/272318.html