Función de aprendizaje GO (Función)

ir serie

1. Hello World of GO Learning
2. Introducción a la gramática de GO Learning
3. Operación de corte de GO Learning
4. Operación de mapas de GO Learning
5. Estructura de la operación de GO Learning
6. Canal de GO Learning (Canal)
7. GO Learning de subprocesos múltiples (goroutine)
8. Función de aprendizaje GO (Función)
9. Interfaz de aprendizaje GO (Interfaz)

prefacio

De acuerdo con las tareas actuales de la empresa, ir aprendiendo es el único camino a seguir. Aunque la industria es difícil, pero las habilidades no son abrumadoras, ¡todavía trabajamos duro! ! !
El método se mencionó en el capítulo anterior sobre la estructura . El método es en realidad similar a la función, pero la diferencia entre el método y la función es que la función no pertenece a ningún tipo, y el método pertenece a un tipo específico . Esta oración también se menciona en el capítulo de estructura, pero hay muchos detalles a los que se debe prestar atención en el uso de funciones, y este artículo brindará explicaciones detalladas.

1. ¿Qué es una función?

  • En el lenguaje Go, una función (Función) es un bloque de código ejecutable ( que extrae una función específica para formar un fragmento de código ) para realizar una tarea u operación específica.
  • Las funciones son los componentes básicos del lenguaje Go, que realiza el mecanismo de modularización y reutilización, haciendo que el código sea más estructurado y mantenible.

Aquí hay una lista de las características que puedo encontrar y pensar (no limitadas a estas):

Características de las funciones en el lenguaje Go:

  • No es necesario declarar prototipo
  • Admite parámetros variables
  • Admite múltiples valores de retorno
  • Compatibilidad con parámetros de retorno con nombre
  • Soporte para funciones y cierres anónimos
  • La función también es un tipo, puede asignar una función a una variable
  • Las funciones no se pueden anidar
  • Las funciones no se pueden sobrecargar como en JAVA

2. Declaración de función

  • Las declaraciones de funciones usan la palabra clavefunc
  • Sintaxis básica:func 函数名(参数列表) 返回值列表 { 函数体 }
  • Convenciones de nomenclatura para nombres de funciones: 1. Es mejor nombrar con mayúsculas y minúsculas, vea el nombre, por ejemplo: ; addNum(a,b int){}2. La primera letra no puede ser un número 3. La primera letra está en mayúscula para indicar que puede ser utilizada por este paquete y otros archivos de paquetes, similares a public, por ejemplo: AddNum(a,b int){}, Las iniciales en minúsculas son similares a private, por ejemplo:addNum(a,b int){}
  • La lista de parámetros está separada por comas, cada parámetro consta de un nombre y tipo de parámetro, por ejemplo:func list(pageNo int, pageSize int) (int, error) { }
  • Si varios parámetros son del mismo tipo, se puede omitir el tipo de parámetro anterior, por ejemplo:func list(pageNo, pageSize int) (int, error) { }
  • Use ...la sintaxis para definir parámetros variables para la función, y la función en ejecución acepta un número variable de parámetros, como: ``
  • Se puede omitir si no hay valor de retorno, por ejemplo:func save(id int, name string) { }
  • Los paréntesis no son obligatorios (ni están disponibles) si se trata de un valor de retorno, por ejemplo:func save(id int, name string) int { }
  • Si hay varios valores de retorno, envuélvalos entre paréntesis y corresponda a la declaración de retorno uno por uno, por ejemplo:func save(id int, name string) (int, string) { ...return 1,'success' }
  • Como se mencionó anteriormente, se admiten funciones de devolución con nombre, como:func divideAndRemainder(a, b int) (quotient, remainder int) { }
  • Use palabras clave funcpara definir funciones, las llaves no pueden comenzar una nueva línea

Código anterior:

3. Llamada de función

  • Al aceptar valores de retorno de función, si se aceptan múltiples valores de retorno uno por uno, por ejemplo:count, result := save(1, "张三")
  • Si solo necesita aceptar uno de los valores de retorno y no el otro, puede usar un guión bajo _para ignorarlo, por ejemplo:count, _ := save(1, "张三")
  • Si el paquete principal quiere llamar a funciones en otros paquetes, las funciones en otros paquetes deben definirse como accesibles fuera del paquete, y la primera letra del nombre de la función debe estar en mayúscula. Por ejemplo, al definir un paquete func1: , necesita para prestar atención al nombre del paquete en este momento func SumNum(a, b int) int { }, debe usar el nombre del paquete para llamar, por ejemplo:s := func1.SumNum(1, 2)

Los siguientes ejemplos son ejemplos de definiciones de funciones comúnmente utilizadas en el lenguaje Go como referencia.
Los ejemplos son mi hermano y yo escribimos uno por uno, la prueba pasó y los resultados de la ejecución se adjuntan, pero aún es un poco complicado verlo con los ojos, es mejor escribirlo usted mismo, pero no importa a los grandes, y no les importa a los pequeños como yo ¡Para el blanco, solo puedes escribirlo paso a paso para resolver varios errores antes de que puedas crecer!

La ruta del paquete es así:
ruta del paquete de funciones

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 语句,并且直接返回了命名的返回值变量
}

El siguiente ejemplo es una llamada a la función definida anteriormente.
Principalmente, la ruta para importar otros paquetes es 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 接口")
}

resultado de la operación:

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. Funciones anónimas

  • En el lenguaje Go se admiten funciones anónimas, es decir, funciones sin nombres de función
  • Se pueden asignar funciones anónimas a las variables.
  • También puede llamar directamente a la función anónima, que es un cierre
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))
}

resultado de la operación:

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

Aquí hay un ejemplo un poco más complicado:

En el siguiente ejemplo, almacenamos la función como miembro en el arreglo fns, la estructura s y la canalización fc, y obtenemos la función para llamar.

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

resultado de la operación:

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

5. Parámetros de función y valores de retorno

  • En Go, una función se puede pasar como argumento o como valor de retorno de otra función

El siguiente es un ejemplo relativamente simple, que acepta un parámetro de tipo función fc y devuelve una función anónima.

package func1

import "fmt"

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

Código de llamada:

package main

import (
	"fmt"

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

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

resultado de la operación:

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

El siguiente es un caso clásico dado por ChatGPT , que es conveniente para una comprensión más profunda de cómo las funciones se usan como parámetros y devuelven valores en escenarios reales. El ejemplo que he probado es ojbk.

  • Las funciones se utilizan como parámetros:
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)
}

resultado de la operación:

PS D:\workspaceGo\src\functionTest\main> go run .\gptFunc.go
加法结果: 15
减法结果: 5
  • Funciones utilizadas como valores de retorno:
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)
}

Resultados de la:

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

6. Función de ejecución de retraso

Características de aplazar:

  • Llamada de retraso de registro de usuario diferido de palabra clave, por ejemplo:defer println(i)
  • La llamada diferida registrada no se ejecutará hasta la devolución, por lo que es muy adecuada para cierre, recuperación de recursos y otras operaciones
  • La instrucción diferida se ejecuta de manera que el primero en entrar sea el último en salir.
  • Las variables en la instrucción defer se determinan en la instrucción defer

Escenarios aplicables para diferir:

  • operación de flujo cerrado
  • liberación de recursos
  • liberación de la conexión de la base de datos
  • esperar…

6.1 diferir primero en entrar último en salir

package main

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

resultado de la operación:

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

Se puede ver a partir de los resultados que el aplazamiento que se repite primero no se ejecutará hasta más tarde.

6.2 función de cierre diferido

package main

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

resultado de la operación:

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

¿Por qué se cambiaron todas a 4? Debido a que el cuerpo del bucle es una función de cierre, se ejecutará inmediatamente después de la declaración, pero la variable i se cambió a 4 cuando se declara la función, por lo que las cuatro funciones anónimas generan 4.

Dado que diferir parece tener muchos casos, ¡múdate aquí!

7. Manejo de errores

  • La mayoría de las funciones en el lenguaje Go devolverán un error errorcomo valor de retorno adicional, el usuario indica si la función se ejecutó con éxito
  • Las funciones de llamada a menudo necesitan verificar si hay errores para que puedan manejarse según corresponda.
  • Para las funciones que no devuelven un valor, puede usar el tipo de error para indicar si la función se ejecutó correctamente o para panicdesencadenar una excepción.

7.1 Uso del error como parámetro de retorno

En el ejemplo, usamos el tipo de error error para indicar si la función se ejecuta correctamente y devolvemos error si la función falla.

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
}

resultado de la operación:

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

7.2 Usar pánico para desencadenar excepciones

En el ejemplo, panic se usa para disparar una excepción para indicar el estado de ejecución de la función, cuando ocurre un error en la función, la excepción se dispara directamente y la ejecución del programa se interrumpe.
**Nota:** Usamos la función de recuperación () para capturar y manejar excepciones para evitar bloqueos del programa. recoverLas funciones solo están deferdisponibles en bloques, así que use diferir en la función main() para detectar excepciones.

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

resultado de la operación:

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

8. Resumen

Las funciones son una parte muy importante del lenguaje Go, brindan la capacidad de modularización, reutilización de código y abstracción. A través de las funciones, podemos dividir la lógica compleja en múltiples módulos pequeños, lo que hace que el código sea más claro, más legible y más fácil de mantener y expandir. La flexibilidad y variedad de funciones permiten utilizar el lenguaje Go para resolver diversos problemas y escenarios.

En esta etapa, todavía estoy en la etapa de aprendizaje del lenguaje Go. Debe haber algunos lugares que no se consideran de manera integral. Todos los ejemplos en este artículo están escritos a mano y ejecutados.
Si tiene alguna pregunta, por favor avise.
¡Házmelo saber en los comentarios! ! ! ¡Aprender juntos y progresar juntos! ! !

Supongo que te gusta

Origin blog.csdn.net/qq_19283249/article/details/132116497
Recomendado
Clasificación