1.不要使用+和fmt.Sprintf操作字串
+操作字串很方便,但是真的很慢,在Go語言裡使用+會導致你的程式跑得可能比指令碼語言還滿,不相信的可以自己做個測試,用+操作,迭代十萬次,Python、Javascript都比Go快很多(是很多噢,不是一點點)
func TestStr(t *testing.T) {
str := ""
for i := 0; i < 100000; i++ {
str += "test"
}
}
複製程式碼
測試結果
PASS: TestStr (3.32s)
str=""
for i in range(100000):
str+="test"
複製程式碼
測試結果:
~/» time python test.py
0.03s user 0.03s system 81% cpu 0.078 total
作為靜態語言的Go,居然在這麼一個段簡單的程式碼上執行效率比Python慢了100倍,不可思議吧?不是Go的問題,而是在Go中使用+處理字串是很消耗效能的,而Python應該是對+操作字串進行了過載優化。(Javascript +操作字串也很快)
最有效的方式是採用buffer
strBuf := bytes.NewBufferString("")
for i := 0; i < 100000; i++ {
strBuf.WriteString("test")
}
複製程式碼
結果可以自己測試,會讓你很驚訝
有一些需要簡單組合兩個字串,用Buffer麻煩了點,比較容易讓人想到的就是用fmt.Sprintf()來組合,很多包裡的原始碼也是這麼寫的。其實fmt的Sprintf也非常慢,如果沒有複雜的型別轉換輸出的情況下,使用strings.Join效能會高很多
func TestStr(t *testing.T) {
a, b := "Hello", "world"
for i := 0; i < 1000000; i++ {
fmt.Sprintf("%s%s", a, b)
//strings.Join([]string{a, b}, "")
}
}
複製程式碼
PASS: TestStr (0.29s)
func TestStr(t *testing.T) {
a, b := "Hello", "world"
for i := 0; i < 1000000; i++ {
//fmt.Sprintf("%s%s", a, b)
strings.Join([]string{a, b}, "")
}
}
複製程式碼
PASS: TestStr (0.09s)
從結果來看strings.Join 比用Sprint快4倍左右吧。
2.對於固定欄位的鍵值對,用臨時Struct,不要用map[string]interface{}
舉個簡單的例子
func TestData(t *testing.T) {
for i := 0; i < 100000000; i++ {
var a struct {
Name string
Age int
}
a.Name = "Hello"
a.Age = 10
}
}
複製程式碼
PASS: TestData (0.04s)
func TestData2(t *testing.T) {
for i := 0; i < 100000000; i++ {
var a = map[string]interface{}{}
a["Name"] = "Hello"
a["Age"] = 10
}
}
複製程式碼
PASS: TestData2 (38.30s)
相差上千倍的效率呢! 在能夠知道欄位的情況下,用臨時Struct在執行期間不需要動態分配內容,並且不需要像map那樣去檢查索引,所以速度會快非常多。