真正在作業中用Go的時間不久,所以也作為新手,總結了一些常見的問題和坑
Go 中指標使用注意點
// 1.空指標反向參考不合法
package main
func main() {
var p *int = nil
*p = 0
}
// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
// runtime error: invalid memory address or nil pointer dereference
// 2.文字或者常量參考也不合法
const i = 5
ptr := &i //error: cannot take the address of i
ptr2 := &10 //error: cannot take the address of 10
Go語言常見內置函式
sort
// sort 包
import "sort"
sort.Strings(keys)
close 用于管道通信,select 用于通信的switch
type T int
func main() {
c := make(chan T)
close(c)
}
// select 用法
var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("received ", i1, " from c1\n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
fmt.Printf("received ", i3, " from c3\n")
} else {
fmt.Printf("c3 is closed\n")
}
default:
fmt.Printf("no communication\n")
}
len、cap
len 用于回傳某個型別的長度或數量(字串、陣列、切片、map 和管道);
cap 是容量的意思,用于回傳某個型別的最大容量(只能用于切片和 map)
new、make
new 和 make 均是用于分配記憶體:new 用于值型別和用戶定義的型別,如自定義結構,make 用于內置參考型別(切片、map 和管道),
它們的用法就像是函式,但是將型別作為引數:new (type)、make (type),new (T) 分配型別 T 的零值并回傳其地址,也就是指向型別 T 的指標,
它也可以被用于基本型別:v := new(int),make (T) 回傳型別 T 的初始化之后的值,因此它比 new 進行更多的作業,new () 是一個函式,不要忘記它的括號
copy、append
用于復制和連接切片
panic、recover
兩者均用于錯誤處理機制
print、println
底層列印函式,在部署環境中建議使用 fmt 包
complex、real、imag
操作復數,使用場景不多
Go不支持函式多載
Go 語言不支持這項特性的主要原因是函式多載需要進行多余的型別匹配影響性能;沒有多載意味著只是一個簡單的函式調度,所以你需要給不同的函式使用不同的名字,我們通常會根據函式的特征對函式進行命名
如果需要申明一個在外部定義的函式,你只需要給出函式名與函式簽名,不需要給出函式體:
func flushICache(begin, end uintptr) // implemented externally
函式也可以以申明的方式被使用,作為一個函式型別,就像:
type binOp func(int, int) int
Go的map遍歷時候變數地址一直用的是同一個
最佳實踐:讀資料可以用key,value,寫資料用地址,如果要把地址賦值給另外的map,那么需要用臨時變數
kvMap := make(map[int]int)
kvMap[0] = 100
kvMap[1] = 101
kvMap[2] = 102
kvMap[3] = 103
for k, v := range kvMap {
println(k, &k, v, &v)
}
// 0 0xc000049e50 100 0xc000049e48
// 1 0xc000049e50 101 0xc000049e48
// 2 0xc000049e50 102 0xc000049e48
// 3 0xc000049e50 103 0xc000049e48
Go遍歷的key,value是值,而不是地址
// Version A:
items := make([]map[int]int, 5)
for i:= range items {
items[i] = make(map[int]int, 1)
items[i][1] = 2
}
fmt.Printf("Version A: Value of items: %v\n", items)
// Version B: NOT GOOD!
items2 := make([]map[int]int, 5)
for _, item := range items2 {
item = make(map[int]int, 1) // item is only a copy of the slice element.
item[1] = 2 // This 'item' will be lost on the next iteration.
}
fmt.Printf("Version B: Value of items: %v\n", items2)
應當像 A 版本那樣通過索引使用切片的 map 元素,在 B 版本中獲得的項只是 map 值的一個拷貝而已,所以真正的 map 元素沒有得到初始化
鎖和 sync 包
并發編程在大部分語言里面都會有,用來解決多個執行緒對臨界資源的訪問,經典的做法是一次只能讓一個執行緒對共享變數進行操作,當變數被一個執行緒改變時 (臨界區),我們為它上鎖,直到這個執行緒執行完成并解鎖后,其他執行緒才能訪問它,Go語言的這種鎖機制是通過sync包中的Mutex來實作訪問的,下面是一個例子,另外在sync包中還有一個讀寫鎖,RWMutex ,其寫互斥的方法與Mutex一樣,讀互斥采用下面的方法
mu sync.Mutex
func update(a int) {
mu.Lock()
a = xxx
mu.Unlock()
}
mu2 sync.RWMutex
mu2.RLock()
mu2.RUnlock()
吳邪,小三爺,混跡于后臺,大資料,人工智能領域的小菜鳥,
更多請關注

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296278.html
標籤:其他
上一篇:基于vue(element ui) + ssm + shiro 的權限框架
下一篇:MMDetection原始碼決議:Faster RCNN(7)--ConvFCBBoxHead,Shared2FCBBoxHead和Shared4Conv1FCBBoxHead類
