這裡列舉的go語言常見坑都是符合go語言語法的,可以正常的編譯,但是可能是執行結果錯誤,或者是有資源洩漏的風險。
當引數的可變引數是空介面型別時,傳入空介面的切片時需要注意引數展開的問題。
func main()
fmt.println(a)
fmt.println(a...)
}
不管是否展開,編譯器都無法發現錯誤,但是輸出是不同的:
[1 2 3]
1 2 3
在函式呼叫引數中,陣列是值傳遞,無法通過修改陣列型別的引數返回結果。
func main()
func(arr [3]int) (x)
fmt.println(x)
}
必要時需要使用切片。
map是一種hash表實現,每次遍歷的順序都可能不一樣。
func main()
for k, v := range m
}
在區域性作用域中,命名的返回值內同名的區域性變數遮蔽:
func foo() (err error)
return
}
recover捕獲的是祖父級呼叫時的異常,直接呼叫時無效:
func main()
直接defer呼叫也是無效:
func main()
defer呼叫時多層巢狀依然無效:
func main() ()
}()panic(1)
}
必須在defer函式中直接呼叫才有效:
func main() ()
panic(1)
}
後台goroutine無法保證完成任務。
func main()
休眠並不能保證輸出完整的字串:
func main()
類似的還有通過插入排程語句:
func main()
goroutine是協作式搶占排程,goroutine本身不會主動放棄cpu:
func main()
}()for {} // 占用cpu
}
解決的方法是在for迴圈加入runtime.gosched()排程函式:
func main()
}()for
}
或者是通過阻塞的方式避免cpu占用:
func main()
os.exit(0)
}()select{}
}
因為在不同的goroutine,main函式中無法保證能列印出hello, world
:
var msg string
var done bool
func setup()
func main()
println(msg)
}
解決的辦法是用顯式同步:
var msg string
var done = make(chan bool)
func setup()
func main()
msg的寫入是在channel傳送之前,所以能保證列印hello, world
func main() ()}}
改進的方法是在每輪迭代中生成乙個區域性變數:
func main() ()}}
或者是通過函式引數傳入:
func main() (i)}}
defer在函式退出時才能執行,在for執行defer會導致資源延遲釋放:
func main()
defer f.close()}}
解決的方法可以在for中構造乙個區域性函式,在區域性函式內部執行defer:
func main()
defer f.close()
}()}
}
切片會導致整個底層陣列被鎖定,底層陣列無法釋放記憶體。如果底層陣列較大會對記憶體產生很大的壓力。
func main()
headermap[name] = data[:1]
}// do some thing
}
解決的方法是將結果轉殖乙份,這樣可以釋放底層的陣列:
比如返回了乙個錯誤指標,但是並不是空的error介面:
func returnserror() error
return p // will always return a non-nil error.
}
func main()
當記憶體傳送變化的時候,相關的指標會同步更新,但是非指標型別的uintptr不會做同步更新。
同理cgo中也不能儲存go物件位址。
go語言是帶記憶體自動**的特性,因此記憶體一般不會洩漏。但是goroutine確存在洩漏的情況,同時洩漏的goroutine引用的記憶體同樣無法被**。
func main()
} ()
return ch
}()for v := range ch }}
上面的程式中後台goroutine向管道輸入自然數序列,main函式中輸出序列。但是當break跳出for迴圈的時候,後台goroutine就處於無法被**的狀態了。
我們可以通過context包來避免這個問題:
func main()
}} ()
return ch
}(ctx)
for v := range ch }}
當main函式在break跳出迴圈時,通過呼叫cancel()
來通知後台goroutine退出,這樣就避免了goroutine的洩漏。
好文點贊收藏
mysql和sqlserver的sql語句區別
mysql 檢視系統內所有資料庫 show databases 查詢資料庫內所有表 show tables 顯示表結構 desc 表名 sqlserver 檢視系統內所有資料庫 select name,database id,create date from sys.databases 查詢資料庫內...
MySQL和Sql Server的sql語句區別
1 自增長列的插入 sqlserver中可以不為自動增長列插入值,mysql中需要為自動增長列插入值。2 獲取當前時間函式 sqlserver寫法 getdate mysql寫法 now 3 從資料庫定位到表。sqlserver寫法 庫名.dbo.表名 或者 庫名.表名 注 中間使用兩個點 sele...
Hive支援Update和Delete語句
文件說了hive從0.14開始支援的update和delete語句,我使用的hive是1.2.1版本。首先在hive site.xml裡配置如下屬性 hive.optimize.sort.dynamic.partition false hive.support.concurrency true hi...