Go基礎之流程[if, for,switch]和函數[func]
流程控制
流程控制有三大類:條件判斷, 循環控制, 無條件跳轉
if:所有語言 都有的一種判斷:如果滿足就做 不滿足就做另一件
if x > 5 {
fmt.println("比5大")
} else {
fmt.println("比5小")
}
不同點:GO在條件判斷語句裏允許聲明一個變量,作用範圍在該條件邏輯塊內
if a := computedValue(); a>5 {
fmt.println("比5大")
} else {
fmt.println("比5小")
}
a出了if語句塊那麽也就超範圍 失效了
fmt.println(a)
多條件: if xxx{} else if xxx{} else{}
goto goto跳轉必須在當前函數內定義好的標簽。(標簽大小寫敏感)
func myFunc() {
i := 0
Here:
println(i)
i++
goto Here
}
for:
Go裏控制邏輯,它可以用來循環讀取數據 又能控制邏輯 還能叠代操作
for xx1, xx2, xx3 { xxx } 其中xx1,xx2, xx3都是表達式
//例子
package main
import "fmt"
func main(){
sum :=0;
for index :=0; index < 10; index ++ {
sum += index
}
fmt.Println("sum is" , sum)
}
有時候需要進行多個賦值操作,go沒有 所以使用平行賦值i, j= i + 1 ,j-1
有時候可以忽略條件1和條件3
sum := 1
for ; sum <1000; {
sum += sum
}
; 也可以省略
在循環體中有兩個關鍵操作 break和continue。break跳出循環 continue 跳出本次循環
break 和 continue 可以跟著標號 用來調到多重循環中的外層循環
for配合 range 可以用於讀取slice和maip的數據
for k, v:=range map {
fmt.println("map",k)
fmt.println("map",v)
}
!!!由於GO支持"多值返回",並且對"多聲明變量不用會報錯"在這種情況下 可以使用_來丟棄不需要使用的返回值
for _, v := range map{
fmt.Println("maps val:",v)
}
switch
有時候你需要寫很多的if-else來實現邏輯處理那麽可以用switch來代替
switch sexpr {
case expr1:
some instructions
case expr2:
some instructions
case expr3:
some instructions
default:
other code
}
其中 sexpr 和exprx 的類型要保持一致。Go的switch非常靈活,表達式不必是常量或證書,執行過程從上到下,直到找到匹配項:
如果switch沒有表達式,它會匹配true
go裏面switch中 默認每個case後面帶有break,配對成功後不會向下執行而是跳出switch 但是可以用fallthrough 強制執行後面的case代碼
函數:
函數是Go裏面的核心設計,通過關鍵字func來聲明
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
//這裏處理邏輯代碼
//返回多個值
return value1, value2
}
func 是聲明一個函數 funcName
函數可以有一個或者多個參數,每個參數後面帶有類型,通過,分割
函數可以返回多個值
//例子
func max(a,b int) int {//a,b int 都是int 縮略一個int
if a > b {
return a
}
return b
}
func main() {
x := 3
y := 4
z := 5
max_xy := max(x, y) //調用函數max
max_xz := max(x, z)
fmt.Printf("max(%d,%d)=%d\n", x, y, max_xy)
}
多返回值
Go函數支持變參,接受變參的函數是有著不定數量的參數的 但是類型保持一致
func myfunc(arg ...int) {}
arg ... int 告訴GO這個函數接受不定數量的參數 在函數體中arg是個slice
for _, n := range arg {
fmt.Pringtf("and the number is : %d\n", n)
}
傳值和傳指針
當我們傳一個參數值到被調用函數裏面時,世紀穿了這個值得一份copy 當在被調用函數中修改參數值的時候,
調用函數中相應實參不會發生任何變化,因為數值變化只作用在copy上。
例子:
package main
import "fmt"
// 函數實現+1操作
func add1(a int) int {
a = a + 1
retrun a //返回一個新值
}
func main() {
x := 3
fmt.Println("x =", x) //應該輸出 "x = 3"
x1 := add1(x) //調用add1()
fmt.Println("x + 1 =", x1) //應該輸出"x+1 =4"
fmt.Println("x = ", x) //應該輸出 "x = 3"
}
!!!上面x 調用了 add1(x) 並且在add1中執行 a = a + 1 操作,但是x變量的值沒有發生變化
解析原因: 當我們調用add1的時候 add1接收的參數其實是x的copy 而不是x本身
如果傳本身呢? 那就是要傳指針了啊
package main
import "fmt"
//簡單的一個函數,實現了參數+1的操作
func add1(a *int) int {
*a = *a + 1 //修改了a的值
retrun *a //返回新值
}
func main() {
x := 3
fmt.Println("x=", x) //應該輸出"x=3"
x1 := addr1(x)
fmt.Println("x+1", x) //應該輸出 4
fmt.Println("x", x) //應該輸出4
}
// 傳指針的好處
1.傳指針使得多個函數能操作同一個對象
2.傳指針比較輕量級(8bytes),只是傳內存地址,我們尅用指針傳遞體積大的結構體。
如果用參數值傳需要copy會花額外多的系統開銷。所以傳遞大的結構體的時候,用指
針是一個明確的選擇
3.Go語言中string, slice, map這三種類型的實現機制類似於指針 可以直接傳遞 不用取地址後傳遞指針
defer:
GO語言中有種不錯的設計 延遲語句 defer。可以在函數中添加多個defer.並且defer按照逆序進行執行
func ReadWrite() bool{
file.Open("file")
//做一些工作
if filurex {
file.Close()
retrun false
}
if filurey {
file.Close()
retrun false
}
file.Close()
retrun false
}
上面代碼太重復 defer解決了這個問題
func ReadWriter() bool{
file.Open("file")
defer file.Close()
if failurex {
return false
}
if failureY {
renturn false
}
return ture
}
!!!如果很多defer引用,那麽defer是采用後進先出的模式
函數作為值,類型
在Go中函數也是變量之一 可以用type來定義。它的類型就是所擁有相同的參數,相同的返回值的一種類型
type typeName func() type
package main
import "fmt"
type testInt func(int) bool //聲明了一個函數類型
func isOdd(integer int) bool {
if integer % 2 == 0 {
return false
}
retrun true
}
func isEven(integer int) bool {
if integer % 2 == 0 {
return true
}
retrun false
}
// 聲明的函數類型在這個地方做了一個參數
func filter(slice []int, f testInt) []int {
var result [] int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func main() {
slice := [] int {1, 2, 3, 4, 5, 7}
fmt.Println("slice = ", slice)
odd := filter(slice, isOdd) // isOdd這個函數當做值 傳遞到了 filter這個函數裏邊
fmt.Println("Odd elements of slice are: ", odd)
even := filter(slice, isEven)
fmt.Println("Even elements of slice are: ", even)
}
用途: 函數當做值 和類型在我們寫一些通用接口時候非常有用 上面例子中testInt類型是個函數類型。 我們可以實現很多種邏輯使得我們程序變得非常靈活
panic和Recover
main 函數 和Init 函數
GO裏面有兩個保留函數: init函數 (應用於所有package) 和main函數 (只能應用於package main)
這2個函數定義時候不能有任何參數和返回值
兩個函數一個包只限制有一個
GO會自動調用init() 和main() 不需要任何地方調用
init() 是可選的 但是main 是必須的
先執行main包 --- 然後導入其他包 重復只導入一次 ----init包
import 包
GO代碼經常用到import這個命令來導入包文件
import( "fmt")
fmt是Go語言的標準庫 , 去goroot 下加載該模塊,
go也支持其他2種方式來加載自己模塊
1.相對路徑 :import "./model" //當前文件同一目錄的model目錄,不推薦這種方式導入
2.絕對路徑 : import "shorturl/model" //架子啊gopath/src/shorturl/model模塊
特殊導入import
1.點操作:
import(
. "fmt"
)
這個.的意思是 這個包導入 有點 後在引用這個包的函數時候不需要前綴 ---> print()
2.別名操作
import(
f "fmt"
)
別名操作調用包函數時候 前綴變成我們的前綴 ---> f.print()
3._操作
import (
"database/sql"
_"github.com...."
)
_操作就是引入該包,不引入包裏面函數,而是調用該包裏面的init函數
2017年12月23日13:49:48 [小路寫·過去篇]
Go基礎之流程[if, for,switch]和函數[func]