Especificación del lenguaje Go: estándares de programación y codificación de alta calidad

1. Introducción

La programación de alta calidad se refiere al uso de altos estándares y buenas prácticas para escribir código que sea legible, mantenible, comprobable y eficaz en términos de rendimiento.

  • ¿Se consideran completamente varias condiciones de contorno?
  • Manejo de excepciones y garantía de estabilidad.
  • Fácil de leer y mantener

(1) Principios de codificación


Desde la perspectiva de las instrucciones, cómo codificar durante el desarrollo puede reducir la cantidad de instrucciones ejecutadas. Varias características y sintaxis del lenguaje varían, pero los principios seguidos por la programación de alta calidad son los mismos, como se muestra a continuación:

  1. Simplicidad: el código debe ser conciso y claro, evitando redundancias y lógicas complejas. El código limpio es más fácil de entender, depurar y mantener.
  2. Legibilidad: el código debe ser fácil de leer y comprender. Utilice nombres significativos de variables y funciones, siga un estilo de codificación coherente y agregue comentarios y documentación adecuados para mejorar la legibilidad del código.
  3. Coherencia: siga convenciones de nomenclatura, estilos de codificación y organización del código coherentes al escribir código. El estilo de codificación coherente hace que el código sea más fácil de entender y mantener.
  4. Modularización: Divide el código en módulos o funciones, cada módulo o función solo es responsable de una tarea clara. El código modular es más fácil de probar, reutilizar y mantener.
  5. Manejo de errores: maneje los errores y las excepciones de manera adecuada. Evite ignorar errores y, en su lugar, implemente mecanismos de manejo de errores adecuados, como devolver un valor de error o generar una excepción.
  6. Gestión de dependencias: utilice módulos Go para gestionar dependencias y garantizar la reproducibilidad y mantenibilidad del código. Puede utilizar Go Modules para gestionar las dependencias del proyecto.
  7. Pruebas: escribir pruebas es un medio importante para garantizar la calidad del código. Escriba pruebas unitarias y pruebas de integración para cubrir diversas funciones y casos extremos del código.
  8. Documentación: escriba documentación clara y precisa, incluidos comentarios de código, descripciones de funciones y documentación del proyecto. Una buena documentación ayuda a otros desarrolladores a comprender y utilizar el código.
  9. Seguridad de concurrencia: en un entorno de subprocesos múltiples, es necesario garantizar la seguridad de concurrencia del código. Esto se puede lograr utilizando mecanismos como Mutex o Channel proporcionados por el lenguaje Go.

(2) Cómo escribir código Go de alta calidad


1. Formato de código

  • gofmt

gofmtEs una herramienta de línea de comandos proporcionada oficialmente por el lenguaje Go para formatear el código Go. Ajusta automáticamente la sangría, los espacios, las posiciones de los corchetes, etc. del código para garantizar la coherencia y legibilidad del código.

Desde la línea de comando, puede usar el siguiente comando para ejecutar gofmtla herramienta:

gofmt -w <文件或目录>

Entre ellos, -wla opción significa escribir el código formateado directamente en el archivo fuente. Si -wno se usa la opción gofmt, el código formateado se enviará a la salida estándar.

Por ejemplo, para formatear main.goun archivo llamado, ejecutaría el siguiente comando:

gofmt -w main.go

Si desea formatear todos los archivos Go en todo el directorio del proyecto, puede ejecutar el siguiente comando:

gofmt -w .

Cabe señalar que gofmtla herramienta modificará directamente el archivo fuente, por lo que antes de ejecutarla, se recomienda hacer una copia de seguridad del código para evitar modificaciones accidentales.

Además, también puede utilizar complementos en algunos editores o IDE, como GoLand, el complemento Go de Visual Studio Code, etc., para activar automáticamente la operación de formateo gofmtde la herramienta. Esto puede formatear automáticamente el código al guardar el archivo, lo que mejora aún más la eficiencia del desarrollo.

  • goimports

goimportsTambién es una herramienta proporcionada oficialmente por el lenguaje Go y agrega una función de importación automática basada en. Además de formatear el código, también detectará y agregará automáticamente declaraciones de importación faltantes, eliminará declaraciones de importación no utilizadas y ordenará y clasificará las declaraciones de importación de acuerdo con ciertas reglas. gofmtgoimports

2. Comentarios

En el lenguaje Go, los comentarios son texto que se utiliza para describir y explicar el código. El lenguaje Go admite dos tipos de comentarios: comentarios de una sola línea y comentarios de varias líneas.

  • Comentarios de una sola línea: //comience con, se utiliza para comentar una sola línea de código o una sola línea de instrucciones.
// 这是一个单行注释
fmt.Println("Hello, World!") // 打印Hello, World!
  • Comentarios de varias líneas: /*comience con y */termine con, se utiliza para comentar código de varias líneas o instrucciones de varias líneas.
/*
这是一个多行注释,
可以跨越多行。
*/
fmt.Println("Hello, World!")
  • Además de describir el código, los comentarios también se pueden utilizar para generar documentación. En el lenguaje Go, la documentación se puede generar utilizando comentarios con formato especial, que se denominan comentarios de documentación o anotaciones de documentación.

Los comentarios de la documentación /*comienzan con, */terminan con y agregan uno antes de cada línea de comentario *. Los comentarios de la documentación pueden contener algunas etiquetas especiales, como @param, @returnetc., para describir los parámetros y los valores de retorno de la función.

/*
calculateSum函数用于计算两个整数的和。

@param a 第一个整数
@param b 第二个整数
@return 两个整数的和
*/
func calculateSum(a, b int) int {
    return a + b
}

Puede utilizar go docel comando para ver los comentarios de la documentación en su código.

go doc <包名>.<函数名>

Por ejemplo, para ver calculateSumlos comentarios de la documentación de una función, puede ejecutar el siguiente comando:

go doc <包名>.calculateSum

Los comentarios son una parte importante a la hora de escribir código claro y legible. Los buenos comentarios pueden ayudar a otros desarrolladores a comprender la intención y la funcionalidad del código y pueden usarse para generar documentación de referencia. Por lo tanto, al escribir código, se recomienda utilizar comentarios para explicar e ilustrar la lógica y la funcionalidad del código.

3. Convención de nomenclatura

La denominación es una parte importante de las especificaciones del código y las reglas de nomenclatura unificadas ayudarán a mejorar la legibilidad del código.

Los nombres de Go comienzan con las letras de la A a la Z o de la A a la Z o un guión bajo, seguidos de cero o más letras, guiones bajos y números (0 a 9). Go no permite signos de puntuación como @, $ y % en los nombres.

  • Go es un lenguaje de programación que distingue entre mayúsculas y minúsculas. Por tanto, Manpower y manpower son dos nombres diferentes.
  • Cuando el nombre (incluidas constantes, variables, tipos, nombres de funciones, campos de estructura, etc.) comienza con una letra mayúscula, como por ejemplo: Grupo1, los objetos que utilizan esta forma de identificador pueden ser utilizados por el código del paquete externo (cliente El programa necesita importar este paquete primero), lo que se llama exportar (como público en lenguajes orientados a objetos);
  • Los nombres que comienzan con una letra minúscula no son visibles fuera del paquete, pero sí son visibles y están disponibles dentro de todo el paquete (como privado en lenguajes orientados a objetos)
Denominación de variables

Al igual que las estructuras, los nombres de las variables generalmente siguen el método de mayúsculas y minúsculas y la primera letra está en mayúscula o minúscula de acuerdo con el principio de control de acceso. Sin embargo, cuando se encuentran sustantivos únicos, se deben seguir las siguientes reglas:

  • Si la variable es privada y el sustantivo único es la primera palabra, use minúsculas, como apiClient
  • En otros casos, se debe utilizar el método de escritura original del sustantivo, como APIClient, repoID, UserID.
  • Ejemplo de error: UrlArray, debe escribirse como urlArray o URLArray
  • Si el tipo de variable es bool, el nombre debe comenzar con Has, Is, Can o Allow.
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
Nombramiento de interfaz

Las reglas de nomenclatura son básicas y los tipos de estructura anteriores. El nombre de la estructura de una sola función tiene el sufijo "er", como Lector, Escritor.

type Reader interface {
        Read(p []byte) (n int, err error)
}
Nomenclatura de archivos

Intente utilizar nombres de archivos significativos que sean cortos, significativos y que deben estar en minúsculas , utilizando guiones bajos para separar palabras individuales.

my_test.go
Denominación del paquete: paquete

Mantenga la coherencia entre el nombre del paquete y el directorio, intente utilizar nombres de paquete significativos, sea breve, significativo y trate de no entrar en conflicto con la biblioteca estándar. Los nombres de los paquetes deben estar en minúsculas y no utilizar guiones bajos ni mayúsculas y minúsculas.

package demo

package main

4. Proceso de control

El control de flujo es una parte importante de cada lenguaje de programación que controla la dirección lógica y la secuencia de ejecución.

Los controles de proceso comúnmente utilizados en el lenguaje Go incluyen if y for, mientras que switch y goto son principalmente estructuras creadas para simplificar el código y reducir el código repetitivo, y pertenecen al control de proceso de clase extendida.

  • Go语言if else(分支结构)

En el lenguaje Go, la palabra clave if es una declaración utilizada para probar una determinada condición (booleana o lógica). Si la condición es verdadera, se ejecutará el bloque de código entre llaves {} después de if; de lo contrario, el bloque de código se ejecutará. ignorado El bloque de código continúa ejecutando el código posterior.

if condition {    
    // do something
}

Si hay una segunda rama, puede agregar la palabra clave else y otro bloque de código basado en el código anterior. El código en este bloque de código solo se ejecutará cuando no se cumpla la condición. Los dos bloques de código después de if y else son ramas independientes, y sólo se puede ejecutar una de ellas.

if condition {
    // do something
} else {
    // do something
}

Si hay una tercera rama, puedes utilizar la siguiente forma de tres ramas independientes:

if condition1 {
    // do something
} else if condition2 {
    // do something 
} else {
    // catch-all or default
}

No hay límite para el número de ramas else if, pero por razones de legibilidad del código, es mejor no agregar demasiadas estructuras else if después de if. Si debe utilizar este formulario, coloque primero las condiciones que se cumplan. como sea posible.

  • Go语言switch case语句

No es necesario que la expresión sea una constante o incluso un número entero. El caso se evalúa de arriba a abajo hasta que se encuentra un elemento coincidente. Si el modificador no tiene expresión, coincide con verdadero.

El lenguaje Go ha mejorado el diseño de sintaxis de switch. Caso y caso son bloques de código independientes. No es necesario saltar del bloque de código de caso actual a través de la declaración de interrupción para evitar la ejecución a la siguiente línea. El código de muestra es el siguiente:

var a = "hello"
switch a {
case "hello":
    fmt.Println(1)
case "world":
    fmt.Println(2)
default:    
    fmt.Println(0)}

//代码输出: 1

En el ejemplo anterior, cada caso está en formato de cadena y usa la rama predeterminada. El lenguaje Go estipula que cada conmutador solo puede tener una rama predeterminada.

  • Go语言for循环结构

Al utilizar declaraciones de bucle, debe prestar atención a los siguientes puntos:

  • La llave de apertura { debe estar en la misma línea que for.
  • El bucle for en el lenguaje Go es el mismo que el lenguaje C, lo que permite definir e inicializar variables en condiciones de bucle. La única diferencia es que el lenguaje Go no admite declaraciones de asignación múltiples separadas por comas. Se debe utilizar la asignación paralela para inicializar asignaciones múltiples. declaraciones variables.
  • El bucle for del lenguaje Go también admite continuar y interrumpir para controlar el bucle, pero proporciona un descanso más avanzado, que puede elegir qué bucle interrumpir, como en el siguiente ejemplo:
for j := 0; j < 5; j++ {
    for i := 0; i < 10; i++ {
        if i > 5 {
            break JLoop        
        }        
        fmt.Println(i)
    }
}

JLoop:// ...

En el código anterior, la instrucción break termina el bucle externo en la etiqueta JLoop.

5. Manejo de errores y excepciones

Go adopta un enfoque diferente al de otros lenguajes cuando se trata de manejo de errores y excepciones. El manejo de errores en el lenguaje Go se realiza devolviendo valores de error en lugar de utilizar un mecanismo de excepción.

error sencillo
  • En el lenguaje Go, errors.New()las funciones se utilizan para crear un nuevo objeto de error. Recibe un parámetro de cadena como información de descripción del error y devuelve un valor del tipo de error. Determine el tipo de error específico juzgando la instancia del objeto de error.
err := errors.New("something error")
  • fmt.Errorf() Crear objeto de error de interfaz de error
err := fmt.Errorf("发生了错误:%s", reason)

Puede imprimir la representación de cadena de un valor llamando a la función fmt.Printf y proporcionando el marcador de posición %s. Para otros tipos de valores, siempre que podamos escribir un método String para este tipo, podemos personalizar su representación de cadena.

Para un valor de tipo de error, su representación de cadena depende de su método de Error. En el caso anterior, si la función fmt.Printf encuentra que el valor impreso es un valor de tipo error, llamará a su método Error. Este tipo de función de impresión en el paquete fmt realmente hace esto.

Por cierto, cuando queremos generar información de error a través de plantillas y obtener el valor del error, podemos usar la función fmt.Errorf. Lo que realmente hace esta función es llamar primero a la función fmt.Sprintf para obtener el mensaje de error exacto, luego llamar a la función errores.New para obtener el valor del tipo de error que contiene el mensaje de error y finalmente devolver el valor.

Envolver y desenvolver incorrectamente

En el lenguaje Go, el paquete de errores en la biblioteca estándar proporciona Wraplas Unwrapfunciones y, que se refieren al empaquetado y desempaquetado de errores en el mecanismo de manejo de errores.

  • El ajuste de errores se refiere a ajustar el error original en un nuevo error para proporcionar más información contextual al manejar errores. Hacer esto conserva la información de la pila del error original y le asocia el nuevo error.
  • El desempaquetado de errores se refiere a extraer el error original del error empaquetado. Hacer esto le permitirá obtener los detalles del error original si es necesario.

Actualmente, las API proporcionadas en la biblioteca estándar de Go para empaquetar errores incluyen fmt.Errorf y errores.Join. fmt.Errorf es el más utilizado. fmt.Errorf también admite empaquetar múltiples errores a la vez a través de múltiples %ws. Aquí hay un ejemplo completo:

func main() {
    err1 := errors.New("error1")
    err2 := errors.New("error2")
    err3 := errors.New("error3")

    err := fmt.Errorf("wrap multiple error: %w, %w, %w", err1, err2, err3)
    fmt.Println(err)
    e, ok := err.(interface{ Unwrap() []error })
    if !ok {
        fmt.Println("not imple Unwrap []error")
        return
    }
    fmt.Println(e.Unwrap())
}

El resultado de ejecución de muestra es el siguiente:

wrap multiple error: error1, error2, error3
[error1 error2 error3]

Vemos que varios errores empaquetados a la vez por fmt.Errorf se muestran en una línea después de convertirse en String.

errors.JoinSe utiliza para agrupar un conjunto de errores en un solo error. El siguiente es un ejemplo del uso de errores. Únase para empaquetar varios errores a la vez:

func main() {
    err1 := errors.New("error1")
    err2 := errors.New("error2")
    err3 := errors.New("error3")

    err := errors.Join(err1, err2, err3)
    fmt.Println(err)
    errs, ok := err.(interface{ Unwrap() []error })
    if !ok {
        fmt.Println("not imple Unwrap []error")
        return
    }
    fmt.Println(errs.Unwrap())
}

El resultado de este ejemplo es el siguiente:

$go run demo2.go
error1
error2
error3
[error1 error2 error3]

Vemos que después de que se empaquetan varios errores al mismo tiempo a través de errores. Las uniones se convierten en cadenas, cada error ocupa una línea separada.

Mala decisión
  1. errors.Is(err, target): determina errsi se trata de targetun error de tipo y devuelve un valor booleano. Esta función se utiliza para determinar si el tipo de error coincide.
    if errors.Is(err, io.EOF) {
        fmt.Println("遇到了文件末尾")
    }
  2. errors.As(err, target): Error errconvertido a targettipo, devolviendo un valor booleano. Esta función se utiliza para convertir errores en tipos específicos de errores y manejarlos en consecuencia.
    var n *net.OpError
    if errors.As(err, &n) {
        fmt.Println("遇到了网络错误:", n)
    }
Uso de excepción de pánico y recuperación

pánico:

1. Función incorporada
2. Si se escribe una declaración de pánico en la función F, el código que se ejecutará posteriormente finalizará. Si hay una lista de funciones diferidas para ejecutar en la función F donde se encuentra el pánico, se ejecutado en el orden inverso de aplazar. 3. Devuelve la función
F La persona que llama G, en G, el código después de llamar a la función F no se ejecutará. Si hay una lista de funciones de aplazar para ejecutar en la función G, será ejecutado en el orden inverso de aplazar. El aplazamiento aquí es algo similar a try-catch-finally. finalmente
4. Hasta que la rutina salga por completo e informe un error

recuperar:

1. Función incorporada
2. Se utiliza para controlar el comportamiento de pánico de una rutina y capturar el pánico, afectando así el comportamiento de la aplicación
3. Sugerencias de llamadas generales
a) En la función de aplazamiento, utilice el receptor para finalizar el proceso de pánico de una gojroutine y restaurarla. Ejecución de código normal
b) Se puede obtener el error pasado por pánico

En pocas palabras: Go puede generar una excepción de pánico, luego capturar la excepción mediante recuperación en aplazamiento y luego manejarla normalmente.

Supongo que te gusta

Origin blog.csdn.net/weixin_53472334/article/details/132405439
Recomendado
Clasificación