Fonction d'apprentissage GO (Fonction)

ALLER série

1. Hello World of GO Learning
2. Introduction à la grammaire de GO Learning
3. Opération de découpage de GO Learning
4. Opération de carte de GO Learning
5. Opération de structure de GO Learning
6. Channel of GO Learning (Channel)
7. GO Learning de Multithreading (goroutine)
8. Fonction d'apprentissage GO (Fonction)
9. Interface d'apprentissage GO (Interface)

avant-propos

Selon les tâches actuelles de l'entreprise, aller apprendre est la seule voie à suivre.Bien que l'industrie soit difficile, mais les compétences ne sont pas écrasantes, nous travaillons toujours dur ! ! ! La méthode a été mentionnée dans le chapitre sur la structure
avant . La méthode est en fait similaire à la fonction, mais la différence entre la méthode et la fonction est que la fonction n'appartient à aucun type et que la méthode appartient à un type spécifique . Cette phrase est également mentionnée dans la structure. , mais de nombreux détails doivent être pris en compte dans l'utilisation des fonctions, et cet article donnera des explications détaillées.

1. Qu'est-ce qu'une fonction ?

  • Dans le langage Go, une fonction (Function) est un bloc de code exécutable ( extraction d'une fonction spécifique pour former un fragment de code ) permettant d'effectuer une tâche ou une opération spécifique.
  • Les fonctions sont les composants de base du langage Go, qui réalise le mécanisme de modularisation et de réutilisation, rendant le code plus structuré et maintenable.

Voici une liste des fonctionnalités que je peux trouver et auxquelles je peux penser (sans s'y limiter):

Caractéristiques des fonctions en langage Go :

  • Pas besoin de déclarer le prototype
  • Prend en charge les paramètres variables
  • Prend en charge plusieurs valeurs de retour
  • Prise en charge des paramètres de retour nommés
  • Prise en charge des fonctions anonymes et des fermetures
  • La fonction est aussi un type, vous pouvez affecter une fonction à une variable
  • Les fonctions ne peuvent pas être imbriquées
  • Les fonctions ne peuvent pas être surchargées comme en JAVA

2. Déclaration de fonction

  • Les déclarations de fonction utilisent le mot-cléfunc
  • Syntaxe de base :func 函数名(参数列表) 返回值列表 { 函数体 }
  • Conventions de nommage pour les noms de fonction : 1. Il est préférable de nommer avec la casse camel, voir le nom, par exemple : ; addNum(a,b int){}2. La première lettre ne peut pas être un chiffre ; 3. La première lettre est en majuscule pour indiquer qu'elle peut être utilisée par ce package et d'autres fichiers de package, similaires à public, par exemple : AddNum(a,b int){}, Les initiales en minuscules sont similaires à private, par exemple :addNum(a,b int){}
  • La liste des paramètres est séparée par des virgules, chaque paramètre se compose du nom et du type du paramètre, par exemple :func list(pageNo int, pageSize int) (int, error) { }
  • Si plusieurs paramètres sont du même type, le type de paramètre précédent peut être omis, par exemple :func list(pageNo, pageSize int) (int, error) { }
  • Utilisez ...la syntaxe pour définir des paramètres variables pour la fonction, et la fonction en cours d'exécution accepte un nombre variable de paramètres, tels que : ``
  • Il peut être omis s'il n'y a pas de valeur de retour, par exemple :func save(id int, name string) { }
  • Les parenthèses ne sont pas obligatoires (ou disponibles) s'il s'agit d'une valeur de retour, par exemple :func save(id int, name string) int { }
  • S'il y a plusieurs valeurs de retour, placez-les entre parenthèses et faites correspondre l'instruction de retour une par une, par exemple :func save(id int, name string) (int, string) { ...return 1,'success' }
  • Comme mentionné ci-dessus, les fonctions de retour nommées sont prises en charge, telles que :func divideAndRemainder(a, b int) (quotient, remainder int) { }
  • Utilisez des mots clés funcpour définir les fonctions, les accolades ne peuvent pas commencer une nouvelle ligne

Code ci-dessus :

3. Appel de fonction

  • Lors de l'acceptation des valeurs de retour de fonction, si plusieurs valeurs de retour sont acceptées une par une, par exemple :count, result := save(1, "张三")
  • Si vous n'avez besoin d'accepter qu'une des valeurs de retour et que l'autre ne le fait pas, vous pouvez utiliser un trait de soulignement _pour l'ignorer, par exemple :count, _ := save(1, "张三")
  • Si le package principal veut appeler des fonctions dans d'autres packages, les fonctions des autres packages doivent être définies comme accessibles en dehors du package et la première lettre du nom de la fonction doit être en majuscule. Par exemple, lors de la définition d'un package func1 : , vous devez pour faire attention au nom du package à ce moment func SumNum(a, b int) int { }, vous devez utiliser le nom du package pour appeler, par exemple :s := func1.SumNum(1, 2)

Les exemples suivants sont des exemples de définitions de fonctions couramment utilisées dans le langage Go à titre de référence.
Les exemples sont mon frère et moi avons tapé un par un, le test est passé, et les résultats de course sont joints, mais c'est quand même un peu compliqué à voir avec les yeux, il vaut mieux le taper soi-même, mais ce n'est pas grave pour les grands, et peu importe pour les petits comme moi. Pour les blancs, tu ne peux que taper pas à pas pour résoudre diverses erreurs avant de pouvoir grandir !

Le chemin du package ressemble à ceci :
chemin d'accès au package de fonctions

package func1

import "fmt"

// 定义无参数无返回值函数
func test() {
    
    
	fmt.Println("call test函数")
}

// 定义有参数无返回值函数,此函数私有的,只有内部可调
func addNum(a, b int) {
    
    
	c := a + b
	fmt.Printf("a + b = c %+v\n", c)
}

// 定义有参数有一个返回值函数, 次函数共有的,内部、外部包均可调
func SumNum(a, b int) int {
    
    
	c := a + b
	return c
}

// 定义可变参数函数
func ParamsFunc(params ...string) {
    
    
	for index, item := range params {
    
    
		fmt.Printf("可变参数为 %d:%+v\n", index, item)
	}
}

// 定义有参数有多个返回值函数
func List(pageNo, pageSize int) (int, []string) {
    
    
	fmt.Printf("查询操作...%d, %d", pageNo, pageSize)
	result := []string{
    
    "特斯拉", "广汽", "丰田", "宝马", "奥迪"}
	return 5, result
}

// 定义命名返回函数
func divideAndRemainder(a, b int) (quotient, remainder int) {
    
    
	quotient = a / b
	remainder = a % b
	return // 省略了 return 语句,并且直接返回了命名的返回值变量
}

L'exemple suivant est un appel à la fonction définie ci-dessus.
Principalement, le chemin pour importer d'autres packages est gotest.com/test/src/functionTest/func1

package main

import (
	"fmt"

	"gotest.com/test/src/functionTest/func1"
)

func main() {
    
    
	// 调用本包中的 save 函数,接受两个返回值
	count1, result := save(1, "张三")
	fmt.Printf("接受 save 函数的两个返回值 count1:%+v, result: %v\n", count1, result)

	// 调用本包中的 save 函数,接受一个返回值
	count, _ := save(1, "张三")
	fmt.Printf("接受 save 函数的一个返回值 count: %+v\n", count)

	// 调用无返回值函数
	list2(1, 10)

	// 调用 func1 包中的 SumNum 函数
	s := func1.SumNum(1, 2)
	fmt.Printf("调用 func1 包中的 SunNum 函数结果:%+v\n", s)
	
		// 调用可变参数函数
	func1.ParamsFunc("特斯拉", "广汽", "丰田", "宝马", "奥迪")

	// 调用 func1 包中的 List 函数
	totalCount, carBrands := func1.List(1, 10)
	fmt.Printf("调用 func1 包中的 List 函数,查询结果:%+v 条,数据:%v\n", totalCount, carBrands)
}

// 定义有参数有多个返回值函数
func save(id int, name string) (int, string) {
    
    
	fmt.Printf("保存%+v,%v\n", id, name)
	return 1, "success"
}

// 定义有多个参数无返回值函数
func list2(pageNo, pageSize int) {
    
    
	fmt.Println("list 接口")
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run funcTest.go
保存1,张三
接受 save 函数的两个返回值 count1:1, result: success
保存1,张三
接受 save 函数的一个返回值 count: 1
list 接口
调用 func1 包中的 SunNum 函数结果:3
可变参数为 0:特斯拉
可变参数为 1:广汽
可变参数为 2:丰田
可变参数为 3:宝马
可变参数为 4:奥迪
查询操作...1, 10调用 func1 包中的 List 函数,查询结果:5 条,数据:[特斯拉 广汽 丰田 宝马 奥迪]

4. Fonctions anonymes

  • Dans le langage Go, les fonctions anonymes sont prises en charge, c'est-à-dire les fonctions sans nom de fonction
  • Des fonctions anonymes peuvent être affectées à des variables
  • Vous pouvez également appeler directement la fonction anonyme, qui est une fermeture
package main

import "fmt"

func main() {
    
    
	// 定义匿名函数直接调用
	func() {
    
    
		fmt.Println("匿名函数调用!")
	}()
	// 定义匿名函数赋值给变量 hello
	hello := func() {
    
    
		fmt.Println("Hello 函数调用!")
	}
	// 调用匿名函数
	hello()
	// 定义有参数的匿名函数
	sum := func(a, b int) int {
    
    
		return a + b
	}
	fmt.Printf("加法计算:%+v\n", sum(1, 2))
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\anonymousFunc.go
匿名函数调用!
Hello 函数调用!
加法计算:3

Voici un exemple un peu plus compliqué :

Dans l'exemple suivant, nous stockons la fonction en tant que membre dans le tableau fns, la structure s et le pipeline fc, et obtenons la fonction à appeler.

package main

func main() {
    
    
	// 定义数据,元素类型是一个函数
	fns := [](func(a int) int){
    
    func(a int) int {
    
     return a + 1 }, func(a int) int {
    
     return a + 2 }}
	// 获取数组中的第一个函数调用,传参 10
	for _, fn := range fns {
    
    
		println(fn(10))
	}

	// 定义一个结构体,成员是一个 函数,调用结构体的 函数成员
	s := struct {
    
    
		fn func() string
	}{
    
    
		fn: func() string {
    
     return "Hello World!" },
	}
	println(s.fn())

	// 定义一个管道,发送一个函数,再接受到函数进行调用
	fc := make(chan func() string, 2)
	fc <- func() string {
    
     return "fc: Hello World!" }
	println((<-fc)())
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\anomymousFunc2.go
11
12
Hello World!
fc: Hello World!

5. Paramètres de fonction et valeurs de retour

  • En Go, une fonction peut être passée comme argument ou comme valeur de retour d'une autre fonction

Voici un exemple relativement simple, qui accepte un paramètre de type de fonction fc et renvoie une fonction anonyme.

package func1

import "fmt"

func CallFunc(fc func()) func() {
    
    
	fmt.Println("接受到函数 fc, 开始回调!")
	// 返回一个匿名函数
	return func() {
    
    
		fc()
		fmt.Println("call back...")
	}
}

Indicatif d'appel :

package main

import (
	"fmt"

	"gotest.com/test/src/functionTest/func1"
)

func main() {
    
    
fc := func() {
    
    
		fmt.Println("我是参数 fc 执行!")
	}
	fr := func1.CallFunc(fc)
	fr()
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\funcTest.go
接受到函数 fc, 开始回调!
我是参数 fc 执行!
call back...

Ce qui suit est un cas classique donné par ChatGPT , ce qui est pratique pour mieux comprendre comment les fonctions sont utilisées comme paramètres et valeurs de retour dans des scénarios réels. L'exemple que j'ai testé est ojbk.

  • Les fonctions sont utilisées comme paramètres :
package main

import "fmt"

// 函数类型作为参数
type MathFunc func(int, int) int

// 加法函数
func add(a, b int) int {
    
    
	return a + b
}

// 减法函数
func subtract(a, b int) int {
    
    
	return a - b
}

// 计算函数,接收一个函数类型参数,并执行该函数
func calculate(a, b int, op MathFunc) int {
    
    
	return op(a, b)
}

func main() {
    
    
	// 调用 calculate 函数,传入 add 函数作为参数
	result := calculate(10, 5, add)
	fmt.Println("加法结果:", result)

	// 调用 calculate 函数,传入 subtract 函数作为参数
	result = calculate(10, 5, subtract)
	fmt.Println("减法结果:", result)
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\gptFunc.go
加法结果: 15
减法结果: 5
  • Fonctions utilisées comme valeurs de retour :
package main

import "fmt"

// 返回一个加法函数
func getAddFunc() func(int, int) int {
    
    
	// 返回一个匿名函数,来实现计算
	return func(a, b int) int {
    
    
		return a + b
	}
}

// 返回一个减法函数
func getSubtractFunc() func(int, int) int {
    
    
	return func(a, b int) int {
    
    
		return a - b
	}
}

func main() {
    
    
	// 获取加法函数并调用
	addFunc := getAddFunc()
	result := addFunc(10, 5)
	fmt.Println("加法结果:", result)

	// 获取减法函数并调用
	subtractFunc := getSubtractFunc()
	result = subtractFunc(10, 5)
	fmt.Println("减法结果:", result)
}

Résultats du :

PS D:\workspaceGo\src\functionTest\main> go run .\gptFunc2.go
加法结果: 15
减法结果: 5

6. Fonction de retard d'exécution

Caractéristiques du report :

  • Mot-clé différer l'appel de délai d'enregistrement de l'utilisateur, par exemple :defer println(i)
  • L'appel différé enregistré ne sera pas exécuté jusqu'au retour, il est donc très approprié pour la fermeture, la récupération des ressources et d'autres opérations
  • L'instruction de report est exécutée de la manière premier entré, dernier sorti
  • Les variables de l'instruction de report sont déterminées dans l'instruction de report

Scénarios applicables pour le report :

  • opération de fermeture de flux
  • libération des ressources
  • libération de la connexion à la base de données
  • attendez…

6.1 reporter premier entré dernier sorti

package main

func main() {
    
    
	arr := [5]int{
    
    1, 2, 3, 4, 5}
	for i := range arr {
    
    
		defer println(i)
	}
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\deferTest.go
4
3
2
1
0

On peut voir d'après les résultats que le report qui est bouclé en premier ne sera exécuté que plus tard.

6.2 fonction de fermeture différée

package main

func main() {
    
    
	arr := [5]int{
    
    1, 2, 3, 4, 5}
	for i := range arr {
    
    
		defer func() {
    
    
			println(i)
		}()
	}
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\deferTest.go
4
4
4
4
4

Pourquoi sont-elles toutes remplacées par 4 ? Étant donné que le corps de la boucle est une fonction de fermeture, elle sera exécutée immédiatement après la déclaration, mais la variable i a été remplacée par 4 lorsque la fonction est déclarée, de sorte que les quatre fonctions anonymes génèrent 4.

Étant donné que le report semble avoir de nombreux cas, veuillez vous déplacer ici !

7. Gestion des erreurs

  • La plupart des fonctions du langage Go renverront une erreur errorcomme valeur de retour supplémentaire, l'utilisateur indique si la fonction a été exécutée avec succès
  • Les fonctions d'appel doivent souvent vérifier les erreurs afin qu'elles puissent être traitées de manière appropriée
  • Pour les fonctions qui ne renvoient pas de valeur, vous pouvez utiliser le type d'erreur pour indiquer si la fonction est exécutée avec succès ou pour panicdéclencher une exception

7.1 Utilisation de l'erreur comme paramètre de retour

Dans l'exemple, nous utilisons le type d'erreur error pour indiquer si la fonction est exécutée avec succès et renvoyons error si la fonction échoue.

package main

import (
	"errors"
	"fmt"
)

func main() {
    
    
	err := divide(10, 0)
	if err != nil {
    
    
		fmt.Println("发生异常:", err)
	}
}

func divide(a, b int) error {
    
    
	if b == 0 {
    
    
		return errors.New("参数不能为 0")
	}
	return nil
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\errorFunc.go
发生异常: 参数不能为 0

7.2 Utiliser la panique pour déclencher des exceptions

Dans l'exemple, panique est utilisé pour déclencher une exception pour indiquer l'état d'exécution de la fonction. Lorsqu'une erreur survient dans la fonction, l'exception est directement déclenchée et l'exécution du programme est interrompue.
**Remarque :** Nous utilisons la fonction recover() pour intercepter et gérer les exceptions afin d'éviter les plantages du programme. recoverLes fonctions ne sont deferdisponibles que dans les blocs, utilisez donc defer dans la fonction main() pour intercepter les exceptions.

package main

func main() {
    
    
	defer func() {
    
    
		if r := recover(); r != nil {
    
    
			println("发生异常:", r)
		}
	}()
	divide2(10, 0)
}

func divide2(a, b int) {
    
    
	if b == 0 {
    
    
		panic("参数不能为 0")
	}
}

résultat de l'opération :

PS D:\workspaceGo\src\functionTest\main> go run .\panicFunc.go
发生异常: (0xff1920,0x1011638)

8. Résumé

Les fonctions sont une partie très importante du langage Go, elles offrent la capacité de modularisation, de réutilisation de code et d'abstraction. Grâce aux fonctions, nous pouvons diviser une logique complexe en plusieurs petits modules, rendant le code plus clair, plus lisible et plus facile à maintenir et à développer. La flexibilité et la variété des fonctions permettent d'utiliser le langage Go pour résoudre divers problèmes et scénarios.

A ce stade, je suis encore en phase d'apprentissage du langage Go. Il doit y avoir des endroits qui ne sont pas considérés de manière exhaustive.Tous les exemples de cet article sont écrits à la main et exécutés.
Si vous avez des questions, s'il vous plaît aviser.
Faites-moi savoir dans les commentaires! ! ! Apprendre ensemble et progresser ensemble ! ! !

Je suppose que tu aimes

Origine blog.csdn.net/qq_19283249/article/details/132116497
conseillé
Classement