>  기사  >  백엔드 개발  >  Golang의 프로세스 제어를 간략하게 분석한 기사

Golang의 프로세스 제어를 간략하게 분석한 기사

青灯夜游
青灯夜游앞으로
2022-11-25 21:07:206275검색

이 기사는 Go 언어에 대해 설명하고 Go 언어의 기본 프로세스 제어에 대해 설명합니다.

Golang의 프로세스 제어를 간략하게 분석한 기사

Go 언어의 기본 프로세스 제어에는 주로 다음 내용이 포함됩니다.

  • 조건문 if
  • 조건문 스위치
  • 조건문 select
  • 루프문 for
  • 루프문 범위
  • 루프 제어 Goto, Break, Continue

【추천 프로그래밍 튜토리얼: Programming Teaching

1. 조건문 if

Go 언어의 if 조건 판단 형식은 다음과 같습니다. 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(跳出循环)

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
		}
	}
}
break语句可以结束forswitchselect的代码块。break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的forswitch和 select 프론트엔드 학생들은 js에 상대적으로 익숙할 것입니다. go 표현식은 괄호()를 제거하지만 동시에 왼쪽 괄호 는 몇 가지 제약을 줍니다. <code>if >{와 일치는 if 및 표현식과 같은 줄에 배치되어야 합니다. {를 다른 곳에 배치하면 컴파일 오류가 발생합니다. 마찬가지로 else와 일치하는 {else, else와 같은 줄에 작성해야 합니다. if 또는 else if의 오른쪽 중괄호도 같은 줄에 작성해야 합니다.

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循环")
}

🎜🎜2. 조건문 스위치🎜🎜🎜🎜switch 문은 다양한 조건에 따라 다양한 작업을 수행하는 데 사용됩니다. 각 케이스 분기는 고유하며 위에서부터 하나씩 테스트됩니다. , 일치가 이루어질 때까지. Golang 스위치 분기 표현식은 상수에 국한되지 않고 모든 유형이 될 수 있습니다. break는 생략 가능하며 기본적으로 자동 종료됩니다. 🎜rrreee

🎜🎜3. 조건문 select🎜🎜🎜🎜 select 문은 switch 문과 유사하지만 select는 실행 가능한 사례를 무작위로 실행합니다. 실행할 사례가 없으면 실행할 사례가 있을 때까지 차단됩니다. 🎜🎜select는 통신에 사용되는 스위치 문과 유사한 Go의 제어 구조입니다. 각 사례는 전송 또는 수신의 통신 작업이어야 합니다. select는 실행 가능한 사례를 무작위로 실행합니다. 실행할 사례가 없으면 실행할 사례가 있을 때까지 차단됩니다. 기본 절은 항상 실행 가능해야 합니다. 🎜🎜다음은 select 문의 구문을 설명합니다. 🎜rrreeerrreee🎜select는 채널의 데이터 흐름을 모니터링할 수 있습니다. 🎜🎜select의 사용법은 스위치 구문과 매우 유사하며 새로운 선택 블록은 select로 시작하며 각 선택 조건 🎜🎜동등 비교를 사용하여 어떤 조건이든 선택할 수 있는 스위치 문과 비교하여 Select에는 많은 제한 사항이 있습니다. 가장 큰 제한 사항은 각 Case 문이 IO 연산이어야 한다는 것입니다.🎜rrreee🎜Select 문에서 Go는 각 send 및 receive 문은 처음부터 끝까지 순차적으로 평가됩니다. 🎜🎜계속 실행할 수 있는 문이 있으면(즉, 차단되지 않은 경우) 실행할 수 있는 문 중 하나를 선택하여 사용하세요. 어떤 명령문도 실행할 수 없는 경우(즉, 모든 채널이 차단된 경우) 가능한 상황은 두 가지입니다. ① 기본 명령문이 주어지면 기본 프로세스가 실행되고, select 명령문 이후에 프로그램 실행이 시작됩니다. . 성명. ② 기본문이 없을 경우, 최소한 1건의 Case가 진행될 때까지 Select문을 차단합니다. 🎜

🎜일반적인 사용법 - 시간 초과 판단🎜

rrreee

🎜🎜4. 루프 문 for🎜🎜🎜🎜 마찬가지로, go 언어의 for 루프도 js와 비교하여 괄호()를 제거한 것 외에 다른 점에서는 큰 차이가 없습니다. 🎜rrreee

🎜🎜5. 루프 문 range🎜🎜🎜🎜Golang 범위는 (인덱스, 값) 또는 (키, 값)을 반환하는 반복기 작업과 유사합니다. 🎜🎜for 루프의 범위 형식은 슬라이스, 맵, 배열, 문자열 등을 반복할 수 있습니다. 형식은 다음과 같습니다: 🎜rrreeerrreee🎜for와 for range의 차이점은 무엇입니까?🎜🎜주된 이유는 사용 시나리오가 다르기 때문입니다🎜🎜for는 배열과 슬라이스를 순회할 수 있고, 키가 정수 증분인 맵을 순회하고, 문자열을 순회할 수 있습니다. 🎜🎜 for range는 for can에 대해 모두 완료할 수 있습니다. 키가 문자열 유형인 맵을 순회하고 키와 값을 동시에 가져오는 것과 채널 순회를 포함하여 for가 할 수 없는 일을 할 수 있습니다🎜

🎜6. 루프 제어 Goto, Break, Continue🎜🎜🎜루프 제어문🎜🎜루프 제어문은 루프 내 명령문의 실행 과정을 제어할 수 있습니다. 🎜🎜GO 언어는 다음 루프 제어 문을 지원합니다: 🎜

🎜Goto, Break, Continue🎜

rrreee🎜break(루프 중단) 코드> : continue 코드 블록에서(다음 루프를 계속합니다)🎜. 🎜<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으로 문의하시기 바랍니다. 삭제