Go語言學習筆記03--流程控制迴圈語句與函式
1.三目運算子 特別注意!在go語言中不存在三目運算子這個東西! 不是不推薦使用,就是完全不存在! 2.迴圈結構 go語言中有且僅有一種迴圈結構,就是for迴圈結構。不存在while或者dowhile這樣的迴圈結構。 for 表示式1;表示式2;表示式3{ 迴圈體 } 迴圈的結構與識別符號含義幾乎與傳統c語言相同。 (1)表示式1:迴圈變數賦初值 (2)表示式2:迴圈能夠繼續的迴圈條件 (3)表示式3:迴圈變數向著迴圈結束的方向變化 eg: for num:=0; num<10; num++{ fmt.Println(num); } 注意:go語言中的變數作用域為塊級作用域,而不是函式級作用域! 因此定義在for迴圈內部的變數,其作用域僅能夠在for迴圈內部生效, 因此它們在for迴圈之外是不能夠被訪問的!千萬注意! eg: { num:=100; } fmt.Println(num);//違法! 注意:go語言中的for迴圈結構也最好不要寫成拆分形式 num:=0; for ;num<10;num++{ ... } 可能會導致迴圈變數未能正確被賦初值的問題(原因還是go語言的塊級作用域) 瞭解:break輔助流程控制語句 break語句的作用是用來立即結束迴圈,break語句後面的內容不再被執行。 註明:在go語言中允許for後不寫任何內容,而是直接寫出大括號與迴圈體。 但是這種寫法其實是死迴圈的一種表現形式,類似於for(;;){..}這種。 正常來講如果使用這種寫法需要在迴圈體內新增break保證迴圈能夠終止。 eg: for{ fmt.Println("hello world!"); break; } 3.輔助控制 go語言中流程控制的輔助語句和c語言中大同小異 break、continue、goto break:跳出所在層迴圈,當前迴圈結束 continue:跳出所在層迴圈的本次迴圈,當前迴圈不結束 goto:跳轉到指定標誌位置 4.函式 在go語言中函式由關鍵詞func指定,函式結構如下所示 語法: func 函式名(引數1 引數1資料型別, 引數2 引數2資料型別, ...){ 函式體 } eg: func getSum(num1 int, num2 int){ fmt.Println(num1+num2); } (1)特別需要注意,在go語言中函式的引數必須指定引數資料型別! //下面的寫法就是一個違法操作! func getSum(num1, num2){ ... } (2)對於go語言而言,由於函式是不能定義在main函式之內的,因此不存在類似JS中函式提升的問題 但是必須瞭然一件事情那就是函式必須宣告之後才能呼叫。 func getSum(num1 int, num2 int){ fmt.Println(num1+num2); } func main(){ //而且形參與實參的資料型別也必須相同 getSum(100,200); } (3)但是函式引數的【值傳遞】與【引用傳遞】問題仍然存在,因此需要注意。 func swap(num1 int, num2 int){ temp := num1; num1 = num2; num2 = temp; } func main(){ var temp1 int = 100; var temp2 int = 80; //賦值傳遞! swap(temp1, temp2); fmt.Println(temp1);//100 fmt.Println(temp1);//80 } (4)函式的不定參列表 go語言中允許宣告不定參函式,其宣告語法採用...三點符號來實現 func 函式名(args ...資料型別){...} 其中args只是一個隨意書寫的形參名稱,與形參本身並無任何影響(本質上是一個數組結構) eg: func getParas(args ...int){ fmt.Printf("%T",args);//[] int } (5)for迴圈的快速遍歷在函式中的作用 對於for迴圈而言,可以通過range關鍵字,對複雜資料型別進行快速遍歷 以不定參函式為例: func getParas(args ...int){ for index,val := range args{ fmt.Printf("%d,%d\n",index,val); } } 本操作類似於傳統c語言或js語言中的for in快速遍歷模式。 而如果在快速遍歷中,有引數不需要書寫,則可以通過匿名變數來進行賦值的隱藏。 func getParas(args ...int){ for _,val := range args{ fmt.Printf("%d\n",val); } } (6)在go語言中,所有的函式都是全域性函式,可以被專案中的所有檔案使用。 不必出現import這種類似匯入的操作 這也就意味著出現了一個非常重要的問題,那就是所有的函式名都是唯一的!不能重複! (7)不定參函式的巢狀使用 函式的不定參傳遞與普通的引數傳遞語法並不相同 func func1(args1 ...int){...} func func2(args2 ...int){ //這樣的操作是違法的,因為args2是int[]型別,而args1則約定了函式需要int型別 //func1(args2); //正確的做法應當是使用下面的做法,將args2的部分引數傳遞到func1中 func1(args2[beginindex:endIndex] ...); } 而這種寫法帶來了一些特殊的注意事項: 1)beginIndex和endIndex都是可寫可不寫,但都表示到哪一個下標為止(不包括這個元素) 2)endIndex如果小於實際傳入的引數個數,則正常載入 3)endIndex若大於實際傳入的引數個數,則出現下標越界的錯誤! eg: func getParas(args ...int){ for index,value := range args{ fmt.Printf("%d,%d\n",index,value); } } func getParas1(args ...int){ getParas(args[:]...); } (8)函式的返回值 go語言中函式的返回值可以說和所有的傳統程式語言都有所不同。雖然也體現在return關鍵詞上, 但是返回值的語法結構卻截然不同。 func 函式名() 返回值型別{ return 返回值; } 在函式宣告的時候,如果函式存在有返回值,則必須在函式宣告的位置指明函式的返回值資料型別 而後在函式內部的函式體重,return後的返回值也必須是這個型別的內容(資料或表示式均可)。 func getSum(num1 int, num2 int) int{ return num1+num2; } 注意事項: 1)如果函式宣告中不存在有返回值型別的說明,那麼在函式體內使用關鍵詞return就是違法的操作 eg: func getSum(num1 int, num2 int){ return num1+num2; } 2)return關鍵詞除了有返回值的含義之外,還具有停止函式的作用。 即return關鍵詞後的語句不再會得到執行。 eg: func getSum(num1 int, num2 int) int{ return num1+num2; fmt.Println("sentence1");//不執行 fmt.Println("sentence2");//不執行 ... //不執行 } 3)另外返回值的語法也可以採用【預先宣告】的寫法,來保證先分配記憶體空間的目的。 在預先宣告的寫法中,return關鍵詞之後就不再需要主動寫明任何內容。 eg: func getSum(num1 int, num2 int)(sum int){ sum = num1 + num2; return; } -------------------------------------------------------------------------------------------------------------------- |特別注意: | 在go語言中是允許函式存在多個返回值的,並且多個返回值必須採用預先宣告寫法 | eg: | func getReturns()(reValue1 int, reValue2 int){ | reValue1 = ......; | reValue2 = ......; | return; | } | func main(){ | num1,num2 := getReturns(); | fmt.Printf("%d, %d",num1, num2); | } -------------------------------------------------------------------------------------------------------------------- (9)函式別名(定義函式型別變數,即建立函式指標) 函式別名是go語言規定,採用關鍵詞type來對函式進行的重新命名處理。 本質上類似於函式指標的獲取。只不過函式別名在面向物件思想中表現的比較重要。 eg: func hanshu1(num int){ fmt.Println(num); } func hanshu2(num int)int{ num+=10; return num; } type FUNC_WITHOUT_RETURN_VALUE func (int) type FUNC_WITH_RETURN_VALUE func(int) int func main() { var unparaFunc FUNC_WITHOUT_RETURN_VALUE; unparaFunc = hanshu1; //上面兩句話可以簡化為自動推導型別的一句話 //unparaFunc:=hanshu1; unparaFunc(100); var paraFunc FUNC_WITH_RETURN_VALUE; paraFunc = hanshu2; result := paraFunc(100); fmt.Println(result); } 而函式指標的獲取寫法則是下面的表現形式。其實兩者對比來看區別不大。 如果對比自動推導型別的寫法,就會發現兩者完全一致! eg: func hanshu1(num int){ fmt.Println(num); } func hanshu2(num int)int{ num+=10; return num; } func main() { unparaFunc := hanshu1; unparaFunc(100); paraFunc := hanshu2; result := paraFunc(100); fmt.Println(result); } (10)函式的作用域問題 因為go語言是一個以{}塊來區分作用域的語言,所以嚴格來講並不存在什麼全域性區域性的概念。 但是又因為go語言帶有很濃重的c語言風格,因此可以從某種角度上來講以函式來進行區分。 所以go語言中的作用域是一個比較複雜的邏輯問題。 全域性作用域:go語言認為函式之外的區域,就是全域性作用域, 全域性作用域在程式中永遠存在不會消失 全域性變數:go語言認為在全域性作用域中宣告的變數,就是全域性變數, 全域性變數可以在當前所在檔案的任何位置被訪問到 全域性常量:go語言認為在全域性作用域中宣告的常量,就是全域性常量, 全域性常量也可以在當前所在檔案的任何位置被訪問到 區域性作用域:go語言認為函式之內的區域,就是區域性作用域, 區域性作用域在程式中不會永遠存在,會隨著函式的生命週期而明滅變化。 區域性變數:go語言認為在區域性作用域中宣告的變數,就是區域性變數, 區域性變數僅可以在當前所在的函式中被訪問到,脫離所在函式即宣告失效。 區域性常量:go語言認為在區域性作用域中宣告的常量,就是區域性常量, 區域性常量僅可以在當前所在的函式中被訪問到,脫離所在函式即宣告失效。 變數訪問原則:【就近原則】 由於go語言的作用域複雜而繁瑣,所以變數在訪問時採用就近原則。 即 有區域性常變數存在前提下,區域性常變數生效, 區域性常變數不存在的前提下,上一級區域性常變數生效,直至全域性常變數為止。 注意: 就近原則中的【上一級】,指的是上一個{}大括號範圍中。 --------------------- 作者:Frank·Ming 來源:CSDN 原文:https://blog.csdn.net/u013792921/article/details/84395320 版權宣告:本文為博主原創文章,轉載請附上博文連結!