Maison  >  Article  >  développement back-end  >  Un article analysant brièvement le contrôle des processus dans Golang

Un article analysant brièvement le contrôle des processus dans Golang

青灯夜游
青灯夜游avant
2022-11-25 21:07:206219parcourir

Cet article vous apprendra Golang et parlera du contrôle de processus dans les bases du langage Go. J'espère qu'il vous sera utile.

Un article analysant brièvement le contrôle des processus dans Golang

Le contrôle de processus de base du langage Go comprend principalement le contenu suivant :

  • Instruction conditionnelle if
  • Instruction conditionnelle switch
  • Instruction conditionnelle select
  • Instruction de boucle pour
  • Plage d'instructions de boucle
  • Contrôle de boucle Goto, Pause, Continue

【Tutoriel de programmation recommandé : Enseignement de la programmation

1. Instruction conditionnelle if

Le format du jugement conditionnel if en langage Go est le suivant : 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

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
		}
	}
}

Les étudiants front-end doivent être relativement familiers avec js. Par rapport à js, les expressions go suppriment les crochets () , mais donnent en même temps certaines contraintes au crochet gauche . matches <code>if >{ doit être placé sur la même ligne que if et expression Placer { ailleurs déclenchera une erreur de compilation. De la même manière, { qui correspond à else doit également être écrit sur la même ligne que else, et else doit également être écrit sur la même ligne que ci-dessus. L'accolade droite d'un if ou d'un else if est sur la même ligne. 🎜
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. L'instruction conditionnelle switch🎜🎜🎜🎜l'instruction switch est utilisée pour effectuer différentes actions en fonction de différentes conditions. Chaque branche de cas est unique et testée une par une à partir du haut. vers le bas, jusqu'à ce qu'une correspondance soit faite. L'expression de branche de commutateur Golang peut être de n'importe quel type, sans se limiter aux constantes. break peut être omis et se termine automatiquement par défaut. 🎜rrreee

🎜🎜3. Instruction conditionnelle select🎜🎜🎜🎜 L'instruction select est similaire à l'instruction switch, mais select exécutera de manière aléatoire un cas exécutable. S'il n'y a aucun cas à exécuter, il se bloquera jusqu'à ce qu'il y ait un cas à exécuter. 🎜🎜select est une structure de contrôle dans Go, similaire à une instruction switch utilisée pour la communication. Chaque cas doit être une opération de communication, soit en envoi, soit en réception. select exécute de manière aléatoire un cas exécutable. S'il n'y a aucun cas à exécuter, il se bloquera jusqu'à ce qu'il y ait un cas à exécuter. Une clause par défaut doit toujours être exécutable. 🎜🎜Ce qui suit décrit la syntaxe de l'instruction select : 🎜rrreeerrreee🎜select peut surveiller le flux de données du canal 🎜🎜L'utilisation de select est très similaire à la syntaxe switch Un nouveau bloc de sélection commence par select et chaque condition de sélection. est décrit par une instruction case. 🎜🎜Par rapport à l'instruction switch qui peut sélectionner n'importe quelle condition en utilisant la comparaison d'égalité, select a de nombreuses restrictions. La plus grande restriction est que chaque instruction case doit être une opération IO🎜rrreee🎜Dans une instruction select, Go. will Chaque instruction d'envoi et de réception est évaluée séquentiellement du début à la fin. 🎜🎜Si l'une des instructions peut continuer à s'exécuter (c'est-à-dire qu'elle n'est pas bloquée), alors choisissez l'une de ces instructions qui peut être exécutée à utiliser. Si aucune instruction ne peut être exécutée (c'est-à-dire que tous les canaux sont bloqués), alors il y a deux situations possibles : ① Si l'instruction par défaut est donnée, le processus par défaut sera exécuté et l'exécution du programme commencera après la sélection. déclaration. ② S'il n'y a pas d'instruction par défaut, l'instruction select sera bloquée jusqu'à ce qu'au moins un cas puisse être traité. 🎜

🎜Utilisation typique - jugement de délai d'attente🎜

rrreee

🎜🎜4 Instructions de boucle pour🎜🎜🎜🎜 et if. De même, par rapport à js, la boucle for du langage go supprime également les crochets (), et il n'y a pas beaucoup de différence sur d'autres aspects. 🎜rrreee

🎜🎜5. La plage de l'instruction de boucle🎜🎜🎜🎜La plage Golang est similaire à l'opération de l'itérateur, renvoyant (index, valeur) ou (clé, valeur). 🎜🎜Le format de plage de la boucle for peut parcourir des tranches, des cartes, des tableaux, des chaînes, etc. Le format est le suivant : 🎜rrreeerrreee🎜Quelle est la différence entre for et for range ?🎜🎜La raison principale est que les scénarios d'utilisation sont différents🎜🎜car peut parcourir des tableaux et des tranches, parcourir des cartes dont les clés sont des incréments entiers, parcourir des chaînes 🎜🎜for range peut tout compléter for can Il peut faire des choses que for ne peut pas faire, notamment parcourir une carte dont la clé est de type chaîne et obtenir la clé et la valeur en même temps, parcourir le canal🎜

🎜6. Contrôle de boucle Goto, Break, Continue🎜🎜🎜Instructions de contrôle de boucle🎜🎜Les instructions de contrôle de boucle peuvent contrôler le processus d'exécution des instructions dans la boucle. 🎜🎜Le langage GO prend en charge les instructions de contrôle de boucle suivantes : 🎜

🎜Goto, Break, Continue🎜

rrreee🎜break (sortir de la boucle) code> : L'instruction continue (continuer le cycle suivant) <code>break peut mettre fin aux blocs de code de for, switch et select. L'instruction break peut également ajouter une étiquette après l'instruction pour indiquer la sortie du bloc de code correspondant à une certaine étiquette. Les exigences en matière d'étiquette doivent être définies dans le for correspondant, switch</code.> et select blocs de 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视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer