Red de conocimiento informático - Consumibles informáticos - refutando el artículo de mierda "¿Por qué abandoné el lenguaje Go?"

refutando el artículo de mierda "¿Por qué abandoné el lenguaje Go?"

Este artículo ha tenido una amplia circulación. De hecho, no contiene mucha información útil y muchas de sus opiniones son problemáticas. Este artículo se ha discutido en golang-china durante mucho tiempo.

p>

Recientemente, debido al lanzamiento de Rust 1.0 y 1.1, este artículo volvió a aparecer para envenenar a los lectores.

Así que escribí este artículo de refutación para señalar los problemas.

Hubo varias ocasiones en las que pensé: Cuando me levanto, siempre me pregunto: ¿Por qué debería renunciar al lenguaje Go? ¿Es esta la decisión correcta? ¿Es sabio y racional? De hecho, he estado pensando seriamente en este tema.

Para ser claro, abandoné el lenguaje Go (golang) debido a dos "insatisfacciones": en primer lugar, no estaba satisfecho con el lenguaje Go en sí, y en segundo lugar, no estaba satisfecho con algunas personas; en la comunidad lingüística Go. No hay duda de que ésta es una conclusión muy subjetiva. Pero tengo suficientes argumentos objetivos detallados para respaldar esta conclusión aparentemente subjetiva.

Al final del artículo hay un registro de actualización de este artículo.

De hecho, es una conclusión muy subjetiva, porque contiene muchas opiniones cuestionables (está bien usarla para engañar a los novatos de Go).

Sección 0: Mi experiencia con el lenguaje Go.

Permítanme hablar primero de mi experiencia, para evitar ser considerado un hacker de bajo nivel del lenguaje Go sin ningún motivo.

A finales de 2009, se lanzó la primera versión pública del lenguaje Go (golang), envuelta en el aura de "Made by Google", que atrajo a muchos de los primeros usuarios, y yo (Liigo) también estuve entre Después de leerlos, leí información general sobre el lenguaje Go y estudié los tutoriales básicos. Debido a que no estaba satisfecho con el punto y coma y las llaves en su gramática, rápidamente lo olvidé y no lo tomé en serio.

Cuando Go se lanzó por primera vez en 2009, fue debido al aura de “Made by Google” que atrajo a muchos usuarios pioneros de bajo nivel (incluido el autor del artículo y muchos reporteros de TI).

Afortunadamente, después de cinco años de desarrollo, no quedan muchos especuladores únicamente por el halo (Google Trends).

Actualmente, los usuarios reales de Go ya lo han utilizado para la producción real. .

Hablando de insatisfacción con el punto y coma y las llaves en su gramática, quiero decir que este es solo su sentimiento subjetivo personal. Hay muchas personas que están muy satisfechas con el punto y coma y las llaves de Go.

p>

Los diseñadores de lenguaje de Swift, incluida Fruit Company, también están muy satisfechos con este estilo (el punto y coma y las llaves en Swift son básicamente los mismos que los de Go).

Si tan solo Hablando de mis sentimientos subjetivos personales, ¡también puedo decir que la abreviatura fn de Rust también es muy molesta!

Dos años después, a finales de 2011, el plan para lanzar el lenguaje Go 1.0 se puso en la agenda. Hubo más informes relacionados y le presté atención nuevamente. Después de reevaluarlo, decidí involucrarme profundamente en el lenguaje Go. Me suscribí a sus usuarios, locos, desarrolladores, confirmaciones y otros grupos de correo oficiales, insistí en leer los correos electrónicos todos los días y cada actualización del código fuente enviada por los desarrolladores, y envié muchas sugerencias de mejora a Go, incluida la modificación del compilador del lenguaje Go. El código está directamente involucrado en las tareas de desarrollo. Esto continuó durante varios meses.

Esto es un hecho. Hay muchas disputas en golang-china. Si estás interesado, puedes desenterrarlas.

Al principio. En 2012, Go Con el lanzamiento de 1.0, el lenguaje y la biblioteca estándar se han finalizado básicamente y es imposible realizar mejoras importantes. Estoy muy decepcionado de que el lenguaje Go no haya logrado alcanzar un nivel superior y lograr un avance automático antes de 1.0. Se finalizó e incluso pasó a 1.0 con muchos defectos obvios y, por lo tanto, lo alejó gradualmente (por lo que rara vez me importan las cosas después de Go 1.0). Más tarde, cuando vi la Nota de la versión del próximo Go 1.1, descubrí que no había muchos cambios a nivel de idioma, solo algunas reparaciones y mejoras a nivel de biblioteca y herramientas. Sentí que había perdido el poder de crecer. Era muy joven y me decepcioné cada vez más.

Además, las actitudes, palabras y acciones de algunas personas en la comunidad lingüística Go, incluidas algunas personas de Google responsables del desarrollo del lenguaje Go, me disgustaron mucho y me llevaron a abandonar decisivamente el lenguaje Go.

Realmente no sé cuáles son las principales mejoras y muchos defectos obvios que el cartel menciona que se pueden lograr en un corto período de tiempo antes de Go1.0.

Si el cartel menciona la sintaxis anterior Mejoras importantes, como la insatisfacción con el punto y coma y las llaves en Algunas personas (no crea que si tiene todas las funciones como C o Rust, es NB. La suma de varias funciones de NB solo puede costarle 3000 vive, y definitivamente no será una solución milagrosa).

La nota de la versión de Go 1.1 encontró que la capa de idioma no ha cambiado mucho. La razón por la cual la capa de idioma no ha cambiado es por el retroceso. Compromiso de compatibilidad hecho por Go1. Para los lenguajes de nivel industrial, Go1 solo puede ser una ventaja si incluso la capa del lenguaje. Habrá muchas mejoras importantes en cada versión, entonces, ¿quién se atreve a usar el lenguaje Go para el desarrollo de producción (admito que Rust? ¿Los cambios son audaces, pero también muestran que Rust todavía se encuentra en una etapa relativamente ingenua y voluntariosa?

Estoy de acuerdo con las opiniones obstinadas de algunas personas en la comunidad lingüística Go, pero estas personas obstinadas pueden ser razonables. , pero tienen requisitos muy altos para muchas cosas (especialmente la filosofía de diseño de Go).

Siempre que las sugerencias que des estén bien fundadas (la filosofía de diseño del lenguaje es otra cuestión), nunca lo rechazará ciegamente (solo que el período de discusión será más largo).

Con respecto al artículo enviado por el autor sobre cómo agregar archivos BOM a Go, se necesita una explicación adicional.

Cuando se lanzó Go 1.0, el archivo fuente (.go) del lenguaje Go requería claramente que estuviera codificado en UTF8, y está codificado en UTF8 sin BOM.

Nota: la limitación de esta codificación UTF8 sin BOM es solo para el archivo fuente del idioma Go (.go).

¡Esta limitación no significa que los usuarios no puedan procesar archivos de texto UTF8 con BOM!

Creo que esto La restricción no es un problema para escribir programas Go. Hasta ahora, nunca he usado uno con el archivo BOM.

El archivo .go con BOM no solo no tiene mucho significado, sino que también tiene muchos. defectos.

La intención original de BOM es indicar si la codificación es big endian o big endian, utilizada principalmente para UTF16 y UTF32. Para UTF8, BOM no tiene significado (fueron los dos autores). de Go, quien inventó UTF8, que resolvió por completo el problema de codificación global).

Pero, en realidad, debido al bloc de notas txt de MS, para el entorno chino, txt (incluso los archivos fuente C/C) se considerarán como codificación GBK (GBK es una mala codificación),

Para distinguir si es GBK, todavía es UTF8, MS Notepad agrega la lista de materiales basura al frente (aquí ya no se hace cargo de GBK). representa el significado original del orden de bytes. Me pregunto si alguien usa MS Notepad para escribir páginas web y luego generar páginas web UTF8 con BOM. Debe ser interesante.

Este es un ERROR de MS Notepad: no lo hace. ¡Admite la generación de archivos de texto codificados en UTF8 sin BOM!

¡Estos son archivos de texto codificados en UTF8 con BOM, pero definitivamente no son archivos fuente de idioma Go!

Así que, incluso. si los archivos fuente del idioma Go imponen restricciones a los requisitos de codificación UTF8 sin BOM, no habrá ningún problema (y también espero que exista esta restricción).

Aunque el archivo fuente Go luego aceptó UTF8 con BOM, después. Al ejecutar go fmt, la BOM aún se eliminará (porque la BOM no es un huevo). En otras palabras, los archivos fuente de Go con BOM no se ajustan al estilo de codificación del lenguaje Go y eliminarán por la fuerza el encabezado de la BOM.

p>

Como se mencionó anteriormente, la BOM es basura traída por MS, pero el UTF8 de la BOM tiene muchos problemas además de ser inconsistente, porque la BOM incrusta basura al comienzo de la cadena,

lo que lleva a expresiones regulares Las expresiones, las operaciones de encadenamiento de cadenas y otras operaciones están contaminadas por la basura de BOM. Para el lenguaje .go, incluso si el código es exactamente el mismo, el código de verificación como MD5 del archivo será diferente si hay BOM y sin él. BOM.

Entonces, no creo que los usuarios de Go deban preocuparse por la BOM irrelevante.

En los últimos 10 años, yo (Liigo) estuve profundamente involucrado en dos programas Idiomas en la empresa a la que pertenezco. Desarrollo de proyectos. Creo que todavía debería poder opinar sobre cómo juzgar los pros y los contras de un determinado lenguaje de programación, o al menos cómo juzgar si un determinado lenguaje de programación es adecuado para mí.

Sección 1: ¿Por qué no estoy satisfecho con el idioma Go?

Hay muchas cosas que me hacen infeliz sobre el lenguaje Go. Aquí hay algunas de ellas que todavía puedo recordar, básicamente sin ningún orden en particular. Después de leerlo con paciencia, ¿pueden los lectores decir con calma "no me importa"?

1.1 No se permite que la llave izquierda comience en una nueva línea.

Con respecto a la ubicación de las llaves, ha habido un debate continuo en el lenguaje C, C, Java, C# y otras comunidades durante más de diez años. Controversia, nunca consenso. En mi opinión, esta es una decisión muy subjetiva, siempre que no viole los principios y no involucre el bien y el mal, no debería haber un enfoque único para todos. Es suficiente dejar que los programadores o. los equipos toman sus propias decisiones. El lenguaje de programación en sí impone restricciones e impone sus propias preferencias a los demás, lo que no vale la pena. No importa cuál prefieras, definitivamente ofenderás a un grupo de personas que se oponen a ello. Aunque ahora estoy acostumbrado a poner la llave de apertura al final de la línea, la idea de que me prohíban otras opciones me incomoda. En cuanto al lenguaje Go, no logró "unir todas las fuerzas que se pueden unir" y deliberadamente se hizo enemigos. Fue un gran fracaso.

Creo que el mayor invento de Go es go fmt. A partir de ahora, los usuarios de Go ya no tendrán discusiones tan aburridas sobre la posición de las llaves (por supuesto, también habrá menos oportunidades de riego y tiobe rankings).

Esta es la ventaja. El lenguaje Swift también usa un estilo similar al de Go (por supuesto, el cartel también puede despreciar al autor de Swift).

1.2 El compilador. agrega inexplicablemente un punto y coma al final de la línea

Para el lenguaje Go en sí, se puede omitir el punto y coma al final de la línea. Sin embargo, en la implementación de su compilador (gc), para facilitar a los desarrolladores del compilador, se agregó por la fuerza un punto y coma al final de la línea durante la etapa de análisis léxico, lo que a su vez afectó la especificación del lenguaje e hizo cambios en "cómo añadir un punto y coma" Disposiciones especiales. Este enfoque pervertido no tiene precedentes. Cuando la llave izquierda se coloca accidentalmente al principio de la siguiente línea, el punto y coma que agrega automáticamente al final de la línea anterior causará errores de compilación inexplicables (antes de Go 1.0), que ni siquiera él mismo puede explicar. Si realmente no puede manejar los puntos y coma, simplemente no los omita. O bien, los compiladores de Scala y JavaScript son de código abierto. ¿Puede aprender de ellos cómo manejar la omisión de puntos y coma al final de las líneas?

Este es el sentimiento subjetivo personal del autor, pero esta característica me gusta mucho. El lenguaje Swift es similar.

1.3 pone gran énfasis en la velocidad de compilación, sin renunciar a sus funciones. debería proporcionar

Los programadores son humanos, no dioses, e inevitablemente cometerán algunos errores debido a descuido o negligencia durante el proceso de codificación. Algunos de ellos son errores en los que todos pueden caer fácilmente colectivamente (no recuerdo los ejemplos en el lenguaje Go en este momento, y los ejemplos en C incluyen "el destructor de clase base no es una función virtual"). En este momento, el compilador debe ponerse de pie y realizar más comprobaciones, restricciones y trabajos de verificación, tratar de evitar la aparición de errores regulares, tratar de no permitir que el código con errores potenciales pase la compilación y dar algunas advertencias o indicaciones cuando sea necesario. para que los programadores presten atención.

¿No es un compilador sólo una máquina? ¿No se supone que debe hacer más trabajo sucio y reducir la carga mental de las personas? Si el compilador realiza una verificación más, puede evitar que cientos de miles de programadores cometan el mismo error innumerables veces en el futuro y ahorrar innumerables tiempo. Esto es algo bueno con un mérito inconmensurable. Pero los autores del compilador Go no lo creen así. No quieren pasar unas horas más agregando nuevas funciones al compilador. Sienten que es una pérdida y, de hecho, ralentiza la velocidad de compilación. Rechazaron muchas solicitudes de mejoras al compilador con el argumento de que afectarían la velocidad de compilación. Típica incapacidad para comer por atragantamiento. Enfatizar la velocidad de compilación es ciertamente admirable, pero no estoy de acuerdo con ello si renuncia a sus debidas funciones.

La velocidad de compilación es muy importante. Si la velocidad de compilación es lo suficientemente lenta, no importa qué tan bueno sea el lenguaje, nadie lo usará.

Por ejemplo, la compilación incremental/precompilada. El archivo de encabezado de C/C /La compilación simultánea tiene como objetivo mejorar la velocidad de compilación.

Rust1.1 también afirma tener una reducción del 32 % en el tiempo de compilación en comparación con 1.0 (nota: no es velocidad de ejecución).

Por supuesto, Go acaba de ser lanzado. Al hacer esto, la velocidad de compilación es uno de los objetivos del diseño.

Pero creo que el cartel puede estar hablando de errores de compilación causados ​​por el compilador agregando punto y coma. por sí solo.

Creo que {no se puede iniciar una nueva línea en Go es una característica del idioma. Si solucionas esto, se introducirá un nuevo error.

Realmente no puedo pensar. Hay otras formas de ajustar la velocidad de compilación, y no dudo en renunciar a la función que debería proporcionarse (no mencione los genéricos, eso es porque todavía no hay un buen diseño).

1.4 el mecanismo de manejo de errores es demasiado primitivo

El patrón básico para manejar errores en el lenguaje Go es: función Por lo general, se devuelven varios valores, el último valor de los cuales es el tipo de error, que se utiliza para representar el tipo de error. y descripción; cada vez que la persona que llama llama a una función, necesita verificar el error y realizar el manejo de errores correspondiente: if err != nil { / *¿No quieres vomitar después de escribir demasiado código como este?*/ }. Este modo es exactamente el mismo que el manejo de errores muy primitivo en lenguaje C, y no hay ninguna mejora sustancial. En aplicaciones prácticas, es fácil formar declaraciones if else anidadas de múltiples capas. Puede pensar en este escenario de codificación: primero determine si el archivo existe, si existe, abra el archivo, si la apertura es exitosa, lea el archivo. Y si la lectura es exitosa, escriba nuevamente un dato y finalmente cierre el archivo. No olvide lidiar con los errores en cada paso. Una práctica común en la práctica es regresar con anticipación después de juzgar un error de operación para evitar múltiples capas de anidamiento de llaves. Sin embargo, la consecuencia de esto es que una gran cantidad de código de manejo de errores se coloca en una posición destacada en el frente. La lógica de procesamiento convencional quedó enterrada. Más tarde, la legibilidad del código era extremadamente pobre. Además, la interfaz estándar del objeto de error sólo puede devolver un texto de error. A veces, la persona que llama incluso necesita analizar el texto para distinguir diferentes tipos de error. De lo contrario, sólo puede convertir manualmente el tipo de error a un subtipo específico (las ventajas de la escritura estática desaparecen). En cuanto al mecanismo de recuperación de pánico, su defecto fatal es que no se puede utilizar más allá de los límites de la biblioteca. Está destinado a ser un producto semiacabado y, como máximo, sólo se puede reproducir en su propio paquete. Aunque el manejo de excepciones de Java también tiene sus propios problemas (como las excepciones marcadas), generalmente es mucho mejor que el manejo de errores de Go.

En otras palabras, el desarrollo de software lleva medio siglo desarrollándose, pero todavía no hay una mejora sustancial. No creas que hacer un azúcar sintáctico anormal es una revolución.

Solo puedo hablar de errores y excepciones. Son dos cosas diferentes. Tratar todos los errores como excepciones es un comportamiento de SB.

Es precisamente por la llamada solución milagrosa de las excepciones que conduce a muchos comportamientos. de esperar a que otros ayuden a limpiar el trasero (tenga en cuenta que la función de mierda arroja La salida definitivamente no será un tipo de mierda, y los diversos xxx_shits llamados indirectamente por ella también pueden generar varios tipos de excepciones, lo que hace que la captura salga de control):

int main() {

try {

mierda();

} catch( /* ¿Hay miles de tipos de mierda */) {

...

}

}

La sugerencia de Go es recuperarse del pánico. no cruza límites, lo que significa que los errores normales deben ser manejados por pkg.

Este es un comportamiento responsable.

Además, Go es un lenguaje de programación orientado a la concurrencia. ¿Se siente anodino usar try/catch en una gran cantidad de gorutinas?

1.5 El recolector de basura (GC) es imperfecto y tiene fallas importantes

En vísperas de Go 1.0, su El recolector de basura tuvo una pérdida de memoria en el entorno de 32 bits y se ha negado a mejorar, sin mencionar esto. El verdadero defecto fatal del recolector de basura del lenguaje Go es que provoca pausas intermitentes impredecibles en todo el proceso. Algunos programas de servicios en segundo plano de gran tamaño, como servidores de juegos, contenedores de aplicaciones, etc., ocupan grandes cantidades de memoria y tienen una gran cantidad de objetos de memoria. El GC puede tardar varios segundos o incluso más en completar un ciclo de reciclaje. período, todo el proceso del servicio Está bloqueado y pausado desde el mundo exterior, lo que significa que el servicio está interrumpido y no responde, no importa cuán asombroso sea el mecanismo de concurrencia, fallará aquí. El recolector de basura se inicia con regularidad y cada vez que se inicia provocará una breve interrupción del servicio. Si esto continúa, ¿alguien se atreverá a usarlo? Este es un proceso de servidor en segundo plano y es un área de aplicación clave del lenguaje Go. El fenómeno anterior no es algo que haya supuesto una hipótesis, sino un problema real que de hecho existe. No son sólo una o dos familias las que están seriamente preocupadas por él (a finales de 2013 en ECUG Con 2013, Liu Qi de JD.com). mencionó la implementación de GC, aplazamiento y biblioteca estándar del lenguaje Go, y el mayor problema es GC Shen Feng de Meituan. También mencionó que el mayor problema causado por el GC del lenguaje Go es la pausa intermitente en segundo plano; servicios El equipo de desarrollo anterior del juego en línea Xianxiadao también se vio afectado por la recolección de basura de Go). En la práctica, debe esforzarse por reducir la cantidad de objetos en el proceso para que las pausas intermitentes causadas por GC estén dentro de límites aceptables. Aparte de eso, no tiene otra opción (¿todavía desea cambiar el algoritmo de GC usted mismo o incluso cortar el GC? ¿Sigue siendo ese el lenguaje Go?). Fuera del círculo, he estado pensando recientemente, ¿necesito un recolector de basura? ¿Tener un recolector de basura no es necesariamente un paso atrás en la historia? (Es posible que escriba un nuevo artículo de blog para discutir el tema.

)

¡Esto está hablando de sistemas de 32 bits, que definitivamente no es el área de aplicación clave del lenguaje Go! ¡Puedo decir que Go fue diseñado para sistemas de 64 bits y entornos de CPU de múltiples núcleos! (Además, Rust actualmente parece que XP aún no es compatible. ¿Se puede considerar esto como un gran impacto?)

Hubo un problema con los 32 bits en ese momento, pero no era así. un gran impacto en la producción real (¿el cartel todavía usa un sistema de 32 bits? ¿Es solo un sistema de 32 bits? ¿Instalar 4 GB de memoria?). Si se trata de un entorno de microcontrolador de 8 bits, se recomienda no hacerlo. use el lenguaje Go, solo use el lenguaje C.

Y este problema hace tiempo que dejó de existir (puede ver el registro de lanzamiento de Go).

Go solo nació hace 5 años La mejora y mejora de GC es un trabajo continuo. Go1.5, que se lanzará en agosto de 2015, utilizará GC paralelo.

Lo más criticado de GC es que puede causar retrasos, pero. Creo que esto se debe principalmente a la implementación imperfecta de GC.

Si se trata de GC de simultaneidad e incrementalidad perfectas, entonces no debería haber problemas importantes de retraso.

Por supuesto, si es real -Se requiere rendimiento en tiempo, luego use C (tiempo real no significa alto rendimiento, sino tiempo de respuesta controlable).

Para lenguajes como Rust sin GC, es casi imposible desarrollar fácilmente un fondo concurrente programas.

No siempre presumas de que Rust puede reemplazar la capa inferior/media. Para el desarrollo de nivel superior, necesitamos ver quién realmente ha hecho algo con Rust.

1.6 Prohibir variables no utilizadas e importaciones redundantes

El compilador Go no permite que existan variables no utilizadas. Las variables y las importaciones redundantes, si están presentes, conducirán inevitablemente a errores de compilación. Pero la realidad es que durante el proceso de escritura, refactorización y depuración de código, por ejemplo, comentar temporalmente una línea de código puede provocar fácilmente la aparición de variables no utilizadas e importaciones redundantes al mismo tiempo, lo que resulta en un error de compilación directo. Debe responder en consecuencia. Comente las definiciones de variables, luego regrese la página al principio del archivo y comente las importaciones redundantes... Cuando termine el trabajo, si desea recuperar el código que acaba de comentar. Tendrás que seguir varios pasos problemáticos. Hay otro problema molesto al escribir código relacionado con una base de datos: si importa un paquete basado en una base de datos, se compilará y le dará un error que indica que no es necesario importar este paquete no utilizado, pero si confía en el compilador. Al eliminar la importación, se pasa la compilación, pero se informará un error durante el tiempo de ejecución, diciendo que no se puede encontrar el controlador de la base de datos. Puede ver que los programadores están atormentados por personas de ambos lados y finalmente tienen que preguntarle a un maestro: importar; _. Una mejor solución a este problema es tratarlo como una advertencia de compilación en lugar de un error de compilación. Pero los desarrolladores del lenguaje Go son muy tercos y no permitirán tal compromiso.

Sobre este tema, solo puedo decir que la queja del autor es realmente pobre.

¿Por qué no usar errores en lugar de advertencias? Esto es para eliminar errores de bajo nivel en la etapa de compilación. (Puedes pensar en el uso de tantas advertencias en C/C).

Además, incluso si no se utiliza la importación, tiene efectos secundarios, porque la importación provocará el inicio y la inicialización de las variables globales. .

Si no se utiliza algún código, ¿por qué necesitamos realizar init para inicializarlo?

Si las variables se agregan para depurar, ¿no es normal eliminarlas después? ¿Depurar?

p>

Si necesita importar un paquete como fmt o log para depurarlo, eliminar el código de depuración provocará un error de importación.

¿No es así? ¿Sabe que se pueden hacer cosas similares en un paquete de archivos separado? ¿Una función para ayudar a la depuración?

importar (

"fmt"

"log"

)

func logf(cadena de formato, una ... interfaz{}) {

archivo, línea := callerFileLine()

fmt.Fprintf(os.Stderr, "s:d : ", archivo, línea)

fmt.Fprintf(os.Stderr, formato, a...)

}

func fatalf(cadena de formato, una ... interfaz{}) {

archivo, línea := callerFileLine()

fmt.Fprintf(os.Stderr , "s:d: ", archivo, línea)

fmt.Fprintf(os.Stderr, format, a...)

os.Exit(1)

}

import _ es un uso con comportamiento claro, que consiste en ejecutar init y otras funciones en el paquete (puede realizar algunas operaciones de registro).

Tratamiento de advertencias ya que los errores son una filosofía de Go. Por supuesto, en opinión del autor, este es un enfoque idiota.

1.7 Hay demasiadas formas de crear objetos que son confusas

La forma de hacerlo. Crear objetos es llamar a la nueva función, llamar a la función make, llamar al nuevo método y usar la sintaxis de llaves para inicializar directamente la estructura, ¿cuál eliges? Es difícil elegir porque no existe un patrón fijo. Desde un punto de vista práctico, si desea crear un objeto de un tipo de lenguaje integrado (como canal, mapa), generalmente usa la función make para crearlo si desea crear un objeto de un tipo definido; Por la biblioteca estándar o una biblioteca de terceros, primero debe buscarlo en la documentación. Si no hay un método Nuevo, es mejor llamar al método Nuevo para crear el objeto. método, entonces la mejor opción es crear su objeto inicializando la estructura. Este proceso es bastante complicado, a diferencia de C, Java y C#, que se puede realizar directamente con new.

Lo nuevo de C es una mierda. El problema causado por lo nuevo es que el comportamiento de los constructores y las funciones ordinarias es inconsistente. Esta característica del parche realmente no es superior.

Todavía me gusta el lenguaje C. Constructores como fopen y malloc, el constructor es una función ordinaria, y lo mismo ocurre en el lenguaje Go.

En C, además de que el constructor es incompatible con funciones ordinarias, el destructor también lo es con funciones ordinarias, esto se introdujo. Hay muchas trampas.

1.8 Los objetos no tienen constructores ni destructores

Está bien no tener un constructor después de todo, existe una costumbre. Nuevo método, que puede considerarse como un constructor.

Sería más incómodo sin un destructor y RAII no se puede implementar. El trabajo adicional de limpieza manual de recursos sin duda aumenta la carga mental de los programadores. Es inhumano. ¿Aún crees que nuestros programadores no trabajan suficientes horas extras? Hay un destructor en C. Aunque no hay un destructor en Java, hay una declaración final en Go, no hay nada. Sí, tiene un aplazamiento, pero ese aplazamiento es más problemático. Consulte los detalles a continuación.

defer puede anular el comportamiento del destructor y, por supuesto, defer tiene otras tareas. Swift2.0 también introduce una versión simplificada de la función defer.

1.9 Diseño semántico de declaraciones de diferimiento. Definitivamente no es muy razonable

El punto de partida para diseñar declaraciones de aplazamiento en lenguaje Go es bueno: coloque el "código" que libera recursos cerca del lugar donde se crean los recursos, pero posponga (aplace) la "acción". de liberar recursos a Ejecutado antes de que la función regrese. Desafortunadamente, el momento de su ejecución parece un poco irrazonable. Imagine que hay una función que necesita ejecutarse durante mucho tiempo. Hay una declaración de bucle infinito en ella. Los recursos se crean continuamente (o se asigna memoria) dentro del cuerpo del bucle y la declaración de aplazamiento se utiliza para garantizar la liberación. Dado que la función sigue ejecutándose sin regresar, no se ejecutan todas las declaraciones diferidas y una gran cantidad de recursos transitorios creados durante el ciclo se acumulan y no se pueden reciclar. Además, el sistema requiere recursos adicionales para almacenar la lista de aplazamientos, que sigue aumentando. Si esto continúa, no pasará mucho tiempo antes de que todo el sistema colapse debido al agotamiento de los recursos. Para funciones de larga duración, http.ListenAndServe() es un ejemplo típico. En los campos de aplicación clave del lenguaje Go, se puede decir que casi todos los programas de servicios en segundo plano deben tener ese tipo de función, que a menudo es la parte central del programa. Si los programadores usan accidentalmente la declaración aplazar en estas funciones, se puede decir que tendrá infinitas consecuencias. ¿No sería mejor si el diseñador del lenguaje configurara la semántica de aplazar para que se ejecute al final del bloque de código correspondiente (en lugar de cuando la función regresa)? Sin embargo, Go 1.0 se lanzó y finalizó hace mucho tiempo y, para mantener la compatibilidad con versiones anteriores, ya no es posible cambiarlo. ¡Cuidado con las declaraciones diferidas! Te atraparán accidentalmente.

Como se mencionó anteriormente, aplazar tiene otras tareas, es decir, la recuperación ejecutada en aplazar puede capturar la excepción generada por el pánico.

Además, aplazar puede modificar la devolución con nombre tras la devolución. Valor.

Las dos tareas anteriores requieren que aplazar solo se pueda ejecutar cuando la función sale.

El aplazamiento mencionado por el cartel es similar al comportamiento de aplazar en Swift2.0. pero en Swift2.0 aplazar no tiene las dos características anteriores.

El aplazar en Go utiliza el alcance de la función como condición de activación, lo que conducirá al uso incorrecto de la ejecución como se menciona en el cartel (¿Qué idioma no tiene trampas?).

Sin embargo, hay una manera de usar el aplazamiento local en for (el aplazamiento en Go se basa en el alcance de la función):

for {

func() {

f, err:= os.Open(...)

diferir f.Close()

}()

}

Simplemente cree una función de cierre en for. Si no sabe cómo usarla, no culpe a los demás por no decírselo.

1.10 Las funciones integradas de muchos idiomas no admiten tipos definidos por el usuario.

Para in, make, range, canal, mapa, etc., solo admiten tipos integrados de idiomas y lo hacen. no admite tipos definidos por el usuario (?).

Los tipos definidos por el usuario no pueden admitir bucles in. Los usuarios no pueden escribir funciones como marca y rango cuyo "tipo y número de parámetro" o incluso "tipo y número de valor de retorno" son variables. . Esas cosas incorporadas al lenguaje están llenas de rastros de cincelado. Esto refleja las limitaciones, el carácter cerrado, la imperfección y la escasa escalabilidad del diseño del lenguaje, como el trabajo de un novato, sin importar cuán autorizados sean sus diseñadores e implementadores. Lectura ampliada: El lenguaje Go es una antigua idea de diseño de hace 30 años, y las cosas definidas por el usuario son casi ciudadanos de segunda clase (Tikhon Jelvis).

En última instancia, esto se debe a un soporte incompleto para los genéricos.

El lenguaje Go no tiene funciones NB, pero la combinación de funciones y herramientas de Go es buena.

Aquí es donde está el lenguaje Go NB.

1.11 no tiene soporte genérico y las interfaces de tipos de datos comunes son feas

Sin genéricos, List y Set Las interfaces de Los tipos de datos básicos comunes como Árbol y Árbol solo pueden ser feos: el objeto ingresado es de un tipo específico y, después de ser eliminado, se convierte en una interfaz sin tipo {} (que puede considerarse como el tipo básico de todos los tipos). Tienes que forzar la conversión de tipos antes de poder seguir usándolo, lo cual es mudo. El lenguaje Go carece de funciones como min y max. La función abs que calcula el valor absoluto de un valor solo recibe/devuelve tipos decimales de doble precisión. La interfaz de clasificación solo puede usar sort.Interface para evitar impotentemente el tipo de objeto. comparado, etc., etc. Es el resultado de no tener genéricos. Sin genéricos sería difícil que una interfaz fuera elegante. Los desarrolladores de Go no rechazaron explícitamente los genéricos, solo dijeron que no habían encontrado una buena manera de implementarlos (¿se puede aprender de los lenguajes de código abierto)? La realidad es que Go 1.0 ya está finalizado, pero los genéricos aún no. Esas feas interfaces deben existir durante mucho tiempo para mantener la compatibilidad con versiones anteriores.

Go tiene su propia filosofía. Si hay una implementación genérica que no entre en conflicto con la filosofía actual, no pondrán objeciones.

Si es solo un simple estudio (o plagio). ) La sintaxis de los lenguajes que han sido de código abierto es el estilo de diseño de C (o en otras palabras, C siempre se ha diseñado de esta manera, copiando todas las características disponibles), lo que lleva a varios estilos de programación con cerebro dividido.

Los genéricos del tiempo de compilación y los genéricos del tiempo de ejecución pueden no ser totalmente compatibles; mire este ejemplo:

type Adderlt; interface {

Add(a, b T; ) T

p>

}