這篇文章帶大家學習Golang,聊聊Go語言基礎中的流程控制,希望對大家有幫助。
Go語言基礎之流程控制主要包括以下內容:
if 表达式1 { 分支1 } else if 表达式2 { 分支2 } else{ 分支3 }
前端的同學想必對js相對熟悉,相對於js來說,go表達式去掉了括號(),但同時給了一些約束,與if匹配的左括號
{必須與
if和表達式放在同一行,
{放在其他位置會觸發編譯錯誤。同理,與
else相符的
{也必須與
else寫在同一行,
else也必須與上一個
if或
else if右邊的大括號在同一行。
x := 0 // if x > 10 // Error: missing condition in if statement // { // } if n := "abc"; x > 0 { // 初始化语句未必就是定义变量, 如 println("init") 也是可以的。 println(n[2]) } else if x < 0 { // 注意 else if 和 else 左大括号位置。 println(n[1]) } else { println(n[0]) } *不支持三元操作符(三目运算符) "a > b ? a : b"。 package main import "fmt" func main() { /* 定义局部变量 */ var a int = 10 /* 使用 if 语句判断布尔表达式 */ if a < 20 { /* 如果条件为 true 则执行以下语句 */ fmt.Printf("a 小于 20\n" ) } fmt.Printf("a 的值为 : %d\n", a) } 以上代码执行结果为: a 小于 20 a 的值为 : 10
2. 條件語句switchpackage main import "fmt" func main() { /* 定义局部变量 */ var grade string = "B" var marks int = 90 switch marks { case 90: grade = "A" case 80: grade = "B" case 50,60,70 : grade = "C" default: grade = "D" } switch { case grade == "A" : fmt.Printf("优秀!\n" ) case grade == "B", grade == "C" : fmt.Printf("良好\n" ) case grade == "D" : fmt.Printf("及格\n" ) case grade == "F": fmt.Printf("不及格\n" ) default: fmt.Printf("差\n" ) } fmt.Printf("你的等级是 %s\n", grade ) } 以上代码执行结果为: 优秀! 你的等级是 A
每个case都必须是一个通信 所有channel表达式都会被求值 所有被发送的表达式都会被求值 如果任意某个通信可以进行,它就执行;其他被忽略。 如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。 否则: 如果有default子句,则执行该语句。 如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。
package main import "fmt" func main() { 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") } } 以上代码执行结果为: no communicationselect可以監聽channel的資料流select的用法與switch語法非常類似,由select開始的一個新的選擇區塊,每個選擇條件由case語句來描述與switch語句可以選擇任何使用相等比較的條件相比,select有比較多的限制,其中最大的一條限制就是每個case語句裡必須是一個IO操作
select { //不停的在这里检测 case <-chanl : //检测有没有数据可以读 //如果chanl成功读取到数据,则进行该case处理语句 case chan2 <- 1 : //检测有没有可以写 //如果成功向chan2写入数据,则进行该case处理语句 //假如没有default,那么在以上两个条件都不成立的情况下,就会在此阻塞//一般default会不写在里面,select中的default子句总是可运行的,因为会很消耗CPU资源 default: //如果以上都没有符合条件,那么则进行default处理流程 }在一個select語句中,Go會依序從頭到尾評估每一個發送和接收的語句。 如果其中的任一個語句可以繼續執行(即沒有被阻塞),那麼就從那些可以執行的語句中任意選擇一條來使用。如果沒有任何一條語句可以執行(即所有的通道都被阻塞),那麼有兩種可能的情況: ①如果給了default語句,那麼就會執行default的流程,同時程式的執行會從select語句後的語句中恢復。 ②如果沒有default語句,那麼select語句將會被阻塞,直到至少有一個case可以進行下去。
典型用法-逾時判斷
//比如在下面的场景中,使用全局resChan来接受response,如果时间超过3S,resChan中还没有数据返回,则第二条case将执行 var resChan = make(chan int) // do request func test() { select { case data := <-resChan: doData(data) case <-time.After(time.Second * 3): fmt.Println("request time out") } } func doData(data int) { //... }
package main import "fmt" func main() { var b int = 15 var a int numbers := [6]int{1, 2, 3, 5} /* for 循环 */ for a := 0; a < 10; a++ { fmt.Printf("a 的值为: %d\n", a) } for a < b { a++ fmt.Printf("a 的值为: %d\n", a) } for i,x:= range numbers { fmt.Printf("第 %d 位 x 的值 = %d\n", i,x) } } 以上实例运行输出结果为: a 的值为: 0 a 的值为: 1 a 的值为: 2 a 的值为: 3 a 的值为: 4 a 的值为: 5 a 的值为: 6 a 的值为: 7 a 的值为: 8 a 的值为: 9 a 的值为: 1 a 的值为: 2 a 的值为: 3 a 的值为: 4 a 的值为: 5 a 的值为: 6 a 的值为: 7 a 的值为: 8 a 的值为: 9 a 的值为: 10 a 的值为: 11 a 的值为: 12 a 的值为: 13 a 的值为: 14 a 的值为: 15 第 0 位 x 的值 = 1 第 1 位 x 的值 = 2 第 2 位 x 的值 = 3 第 3 位 x 的值 = 5 第 4 位 x 的值 = 0 第 5 位 x 的值 = 0
5. 循環語句range
for key, value := range oldMap { newMap[key] = value }
package main func main() { s := "abc" // 忽略 2nd value,支持 string/array/slice/map。 for i := range s { println(s[i]) } // 忽略 index。 for _, c := range s { println(c) } // 忽略全部返回值,仅迭代。 for range s { } m := map[string]int{"a": 1, "b": 2} // 返回 (key, value)。 for k, v := range m { println(k, v) } } 输出结果: 97 98 99 97 98 99 a 1 b 2
for 和for range有什麼區別?
主要是使用場景不同
for可以遍歷array和slice,遍歷key為整型遞增的map ,遍歷string
for range可以完成所有for可以做的事情,卻能做到for不能做的,包括遍歷key為string類型的map並同時獲取key和value,遍歷channel
#6. 迴圈控制Goto、Break、ContinueGO 語言支援以下幾種循環控制語句:
Goto、Break、Continue1.三个语句都可以配合标签(label)使用 2.标签名区分大小写,定以后若不使用会造成编译错误 3.continue、break配合标签(label)可用于多层循环跳出 4.goto是调整执行位置,与continue、break配合标签(label)的结果并不相同
語句可以結束for
、switch
和select
的程式碼區塊。 break
語句也可以在語句後面加上標籤,表示退出某個標籤對應的程式碼區塊,標籤要求必須定義在對應的for
、switch
和 select
的程式碼區塊上。 <p><code> continue(继续下次循环)
:continue
语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for
循环内使用。在 continue
语句后添加标签时,表示开始标签对应的循环
goto
语句通过标签
进行代码间的无条件跳转。goto
语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto
语句能简化一些代码的实现过程。 例如双层嵌套的for循环要退出时:
func gotoDemo1() { var breakFlag bool for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { // 设置退出标签 breakFlag = true break } fmt.Printf("%v-%v\n", i, j) } // 外层for循环判断 if breakFlag { break } } }
使用goto
语句能简化代码:
func gotoDemo2() { for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { if j == 2 { // 设置退出标签 goto breakTag } fmt.Printf("%v-%v\n", i, j) } } return // 标签 breakTag: fmt.Println("结束for循环") }
再次提醒,需要进技术交流群
的同学,可以加我微信fangdongdong_25
,需要进前端工程师交流群的备注“前端”
,需要进go后端交流群的备注“go后端”
【相关推荐:Go视频教程】
以上是一文淺析Golang中的流程控制的詳細內容。更多資訊請關注PHP中文網其他相關文章!