1. go沒有static關鍵字
面向對象編程中,盡量對函數進行封裝,對於沒有函數變量的對象,使用static關鍵字尤其方便。
go中沒有static關鍵字,必須每次new一個出來。
type Handler struct {
}
func NewHandler() *Handler {
h := &Handler{}
return h
}
func (*Handler) Method_1 (){
}
func (*Handler) Method_2 () {
}
2. go沒有while; do...while循環
go語言里面的for循環比較靈活
func main(){
for {
fmt.Printf("while true\n")
break
}
for i:=0; i < 5; i = i + 1 {
fmt.Printf("while data:%d\n", i)
}
i := 0
for i < 5 {
fmt.Printf("while ok:%d\n", i)
i = i + 1
}
}
3. go每個協程都必須捕獲panic
go中每個協程都必須捕獲panic, 否則任何一個協程問題,都會導致整個程序dump掉。
func no_panic_get(a, b int){
/* //每個go協程都必須捕獲panic, 否則整個程序都會panic
defer func() {
if r := recover(); r != nil {
fmt.Printf("no_panic_get, err:%v\n", r)
}
}()
*/
c := a / b
fmt.Printf("no_panic_get res:%v\n", c)
}
func main(){
defer func() {
if r := recover(); r != nil {
fmt.Printf("exec failed, err:%v\n", r)
} else {
fmt.Printf("exec success\n")
}
}()
go no_panic_get(1,0) //no_panic_get沒有捕獲panic, 程序直接panic崩潰
time.Sleep(time.Duration(5 * time.Second))
}
4. go中巧用defer函數逆序執行
defer函數,是在函數最后執行的。
屬於先申明,后執行原則;多個defer,申明時入棧,出棧時執行,也就是逆序執行。
只要第一個申明的defer,作為最后一個捕獲panic程序執行就可以。
func main(){
defer func() {
fmt.Printf("defer func1\n")
} ()
defer func() {
fmt.Printf("defer func2\n")
} ()
fmt.Printf("main func\n")
}
5. go中巧用interface
interface類似C/C++中的void*類型,可以將任何類型轉為interface類型。
不同的是, interface可以確定保存的是那種類型的數據. 使用 v.(type)
type A struct {
age int
sex string
}
type B struct {
peer []string
name string
}
func main(){
aData := &A{age:19}
bData := &B{[]string{"zhangsan", "lisi"},"wang"}
ctx := make(map[string]interface{}) //容器
ctx["1"] = aData
ctx["2"] = bData
for _, v := range ctx {
switch v.(type) {
case *A:
fmt.Printf("type A %v\n", v)
case *B:
fmt.Printf("type B %v\n", v)
default:
fmt.Printf("type unkown\n")
}
}
}
6. go注意大小寫
go中大小寫區分訪問權限, 在定義函數,定義變量時需要注意。
小寫變量,不能被json序列化。
小寫函數,外部不能訪問。
go1.4 之前版本中, map[int]string, 因為key是int不能正確序列號。
type Stu struct {
Age int
Name string
}
func main(){
ctx := make(map[int]*Stu)
ctx[1] = &Stu{12,"li"} //按照定義順序初始化
ctx[2] = &Stu{ Age:18} //初始化部分字段; 其他字段默認值
jsonres, _ := json.Marshal(ctx)
result := string(jsonres)
fmt.Printf("%s\n", result)
newctx := make(map[int]*Stu)
if err := json.Unmarshal([]byte(result), &newctx); err == nil { //第二個參數需要是一個指針
for k, v := range newctx{
fmt.Printf("k:%v val:%v\n", k, v)
}
}
}
7. go中變量申明后都有默認值
在go語言中,任何類型在聲明后沒有賦值的情況下,都對應一個零值。
- 整形如int8、byte、int16、uint、uintprt等,默認值為0
- 浮點類型如float32、float64,默認值為0
- 布爾類型bool的默認值為false
- 復數類型如complex64、complex128,默認值為0+0i
- 字符串string的默認值為""
- 錯誤類型error的默認值為nil
- 對於一些復合類型,如指針、切片、字典、通道、接口,默認值為nil。而數組的默認值要根據其數據類型來確定。例如:var a [4]int,其默認值為[0 0 0 0]
8. go中可以使用fmt構造一個error類型返回
go語言函數是支持多返回值的,因此在寫go函數時,都會帶一個error類型返回值表示是否有錯誤。
可以使用fmt構造一個error返回。
func getError() error {
a := 1
b := 0
return fmt.Errorf("a/b is not vaild, a:%d b:%d", a, b)
}
func main(){
fmt.Printf("err[%v]", getError())
}