首頁  >  文章  >  後端開發  >  一文淺析Golang中的流程控制

一文淺析Golang中的流程控制

青灯夜游
青灯夜游轉載
2022-11-25 21:07:206216瀏覽

這篇文章帶大家學習Golang,聊聊Go語言基礎中的流程控制,希望對大家有幫助。

一文淺析Golang中的流程控制

Go語言基礎之流程控制主要包括以下內容:

  • #條件語句if
  • ##條件語句switch
  • 條件語句select
  • 循環語句for
  • 循環語句range
  • #循環控制Goto、Break、Continue
  • ##【程式設計教程推薦:
程式設計教學

#1.條件語句ifGo語言中

if##條件判斷的格式如下:

if 表达式1 {
    分支1
} else if 表达式2 {
    分支2
} else{
    分支3
}
前端的同學想必對js相對熟悉,相對於js來說,go表達式去掉了括號()

,但同時給了一些約束,與

if匹配的左括號{必須與if和表達式放在同一行,{放在其他位置會觸發編譯錯誤。同理,與else相符的{也必須與else寫在同一行,else也必須與上一個 ifelse 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. 條件語句switch

#switch 語句用於基於不同條件執行不同動作,每一個case 分支都是唯一的,從上直下逐一測試,直到配對為止。 Golang switch 分支表達式可以是任意型,且不限於常數。可省略 break,預設自動終止。
package 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

3. 條件語句 select

select 語句類似於 switch 語句,但是select會隨機執行一個可執行的case。如果沒有case可運行,它將阻塞,直到有case可運行。

select 是Go中的一個控制結構,類似於用於通訊的switch語句。每個case必須是一個通訊操作,要嘛是發送要嘛是接收。 select 隨機執行一個可運行的case。如果沒有case可運行,它將阻塞,直到有case可運行。一個預設的子句應該總是可運行的。

以下描述了select 語句的語法:

    每个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 communication

select可以監聽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) {
   //...
}

#4. 迴圈語句for

##和if一樣,相對於js,go語言的for迴圈也去掉了括號(),其他並沒有太大的差別。
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

#Golang range類似迭代器操作,傳回 (索引, 值) 或 (鍵, 值)。 for 迴圈的 range 格式可以對 slice、map、陣列、字串等進行迭代循環。格式如下:

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、Continue

迴圈控制語句迴圈控制語句可以控制迴圈體內語句的執行過程。

GO 語言支援以下幾種循環控制語句:

Goto、Break、Continue

    1.三个语句都可以配合标签(label)使用
    2.标签名区分大小写,定以后若不使用会造成编译错误
    3.continue、break配合标签(label)可用于多层循环跳出
    4.goto是调整执行位置,与continue、break配合标签(label)的结果并不相同

break(跳出迴圈): continue(繼續下次迴圈)

break

語句可以結束forswitchselect的程式碼區塊。 break語句也可以在語句後面加上標籤,表示退出某個標籤對應的程式碼區塊,標籤要求必須定義在對應的forswitch和 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中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除