#### 1. 跳出/執行下一次迴圈。 ``` {標簽名}: for true { ... for true { ... break/continue {標簽名} //預設不加標簽,則跳出最近一層迴圈。加了標簽可以跳出標簽定義處所在迴圈 } } ``` #### 2. map的使用註意項。 因為ma ...
1. 跳出/執行下一次迴圈。
{標簽名}:
for true {
...
for true {
...
break/continue {標簽名} //預設不加標簽,則跳出最近一層迴圈。加了標簽可以跳出標簽定義處所在迴圈
}
}
2. map的使用註意項。
因為map是指針,作為參數傳遞時,在函數內部對map作的修改直接修改外部傳遞變數的值。
3. slice(切片)使用註意點。
與map一樣,都可以用make創建,但slice返回的是結構體。當slice作為參數傳遞時,在函數內部修改可能會影響slice
4. 遍歷迴圈for range和排序sort的使用。
package main
import (
"fmt"
"sort"
)
func main() {
sl := []int{219, 373, 543, 351, 523, 625, 436, 252, 121, 567, 896, 454, 342, 734, 464, 423, 164}
min, max := getMinAndMax(sl)
fmt.Println("sl中最小值:", min)
fmt.Println("sl中最大值:", max)
sort.Ints(sl) //根據類型進行正向排序
fmt.Println("切片排序獲取sl中最小值:", sl[0])
fmt.Println("切片排序獲取sl中最大值_1:", sl[len(sl)-1:][0])
sort.Sort(sort.Reverse(sort.IntSlice(sl))) //反射排序
fmt.Println("切片排序獲取sl中最大值_2:", sl[0])
}
func getMinAndMax(arr []int) (min int, max int) {
if len(arr) == 0 {
return
}
min, max = arr[0], arr[0]
for _, v := range arr {
if v > max {
max = v
} else if v < min {
min = v
}
}
return
}
上面代碼執行結果:
sl中最小值: 121
sl中最大值: 896
切片排序獲取sl中最小值: 121
切片排序獲取sl中最大值_1: 896
切片排序獲取sl中最大值_2: 896
5. defer用法。
defer是函數退出前必須執行邏輯,類似棧,後進先出,最後執行要先寫
package main
import (
"fmt"
)
func main() {
fmt.Println("start...")
for i := 0; i < 3; i++ {
defer fmt.Println(i)
}
fmt.Println("end")
}
上面代碼執行結果:
start...
end
2
1
0
defer函數實參是值拷貝進去,所以i++不影響defer中的值。
註意:return之後的defer不會執行;調用os.Exit(1)的函數不執行defer。
package main
import (
"fmt"
)
//return後寫defer
func main() {
fmt.Println("start...")
return
defer fmt.Println("defer邏輯")
fmt.Println("end")
}
//函數中使用了os.Exit(1)
func main() {
fmt.Println("start...")
defer fmt.Println("defer邏輯")
fmt.Println("end")
os.Exit(1)
}
6. 匿名函數用法。
package main
import (
"fmt"
"time"
)
var FunB = func() {
fmt.Println("全局匿名函數")
}
func main() {
fmt.Println("start...")
go func() {
fmt.Println("匿名函數")
}()
a := func() {
fmt.Println("給變數賦值的匿名函數")
}
go a()
go FunB()
time.Sleep(1 * time.Second)
fmt.Println("end")
}
7. defer + recover捕獲panic,不會讓一個panic使整個app程式奔潰的簡單方法,提高程式的健壯性。
package main
import "fmt"
func main() {
testPanic()
fmt.Println("test_end")
}
func testPanic() {
defer func() {
err := recover()
if err != nil {
fmt.Println("panic被捕獲")
}
}()
a := 10
b := 0
fmt.Println("a/b=", a/b)
}
8. 自定義錯誤。
errors.New("自定義錯誤內容")
9. 自定義函數進行多函數單一操作。
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func sub(a, b int) int {
return a - b
}
func nul(a, b int) int {
return a * b
}
type Op func(int, int) int
func do(f Op, a, b int) int {
return f(a, b)
}
func main() {
c, d := 102087, 65421
e := do(add, c, d)
fmt.Println("c+d=", e)
f := do(sub, c, d)
fmt.Println("c-d=", f)
g := do(nul, c, d)
fmt.Println("c*d=", g)
}
10. 介面的使用說明。
介面是一種抽象類型,介面實現時要註意值與指針接收者的問題。
在go語言中,一個類型(主要是struct)可以實現多個不同的介面,介面之間互不影響;也可以多個類型實現同一個介面,即間接實現面向對象的開發方式。go裡面的介面不需要類型(對象)完全實現所有函數方法,介面可以通過在類型中嵌入其它類型來實現。還可以通過介面不斷嵌套創造出新的介面。
註意:go語言中有空介面概念(interface{}),即沒有定義任何函數方法的介面,因此任何類型都實現了空介面,空介面類型的變數也就可以接收任意類型的變數(類似其它面向對象語言中的Object對象),用途非常廣但需要斷言正確,否則實現出現未知錯誤。
11. goroutine 併發使用。
併發是指同一時間段內執行的多個任務。並行是指同一時刻執行多個任務。goroutine是go語言中併發的實現,它類似於線程,但是屬於用戶態的線程,由go語言運行時調度完成,不同於線程由操作系統調度完成。
...
go func(){
//併發執行函數邏輯
}()
...
常用sync.Wait.WaitGroup來解決多個併發中安全問題
12. 多個併發goroutine之前的通信channel應用。
chan類型也和map、slice(切片)類型一樣,用make創建。
-end-