Supongo que la mayor motivación para esto, y el mayor resultado, es una mejora en los tiempos de compilación. El video de vista previa de tecnología hizo que su capacidad para compilar grandes cantidades de código en períodos de tiempo cortos fuera importante (su ejemplo fue 200,000 líneas de código en 8 segundos en una MacBook, sin especificaciones de la máquina).
También en el video tecnológico, mencionan específicamente que una de las formas más importantes que lograron fue cambiando la forma en que se compilaron y vincularon los módulos.
Aquí hay un ejemplo de cómo algo que trabajaría en una corriente de C/C++ sistema:
Clase A se define en el archivo de cabecera C_H e implementado en C_CPP. La clase B deriva de C y se implementa en los archivos B_H y B_CPP. La clase A deriva de B y se implementa en los archivos A_H y A_CPP.
Debido a las cadenas de derivación, A_CPP incluye A_H, B_H, y C_H. B_CPP incluye B_H y C_H. C_CPP incluye C_H. Debido a la naturaleza del preprocesador C, que resulta esencialmente una #include en una operación de cortar y pegar, los contenidos de C_H se ejecutan a través del compilador 3 veces y B_H se ejecuta a través de dos veces.
Además, el contenido de A_CPP, B_CPP y C_CPP todos viven en sus propios archivos de objetos. Por lo tanto, cuando el enlazador va a resolver A.o, se ve obligado a cargar y procesar tanto B.o como C.o. Además, cuando resuelve B.o, tiene que procesar C.o nuevamente.
Los encabezados precompilados pueden ayudar bastante con la primera parte de este problema, pero también pueden ser un dolor real de mantener y conozco a muchos desarrolladores que simplemente no los usan por ese motivo. Asimismo, no cambia fundamentalmente el problema - las cabeceras todavía se procesan en varios niveles varias veces, sólo que ahora un binario precompilado se procesa en lugar de la fuente. Se cortan varios pasos, pero no todo el proceso.
Ir enfoca las cosas de manera diferente. En las palabras que parecen sacadas de la PDF from their tech talk:
"El compilador Ir tira transitiva información de tipo dependencia del fichero objeto - pero sólo lo que necesita Si A.go depende de B.go depende C. .go: - compilar C.go, B.go, luego A.go. - para compilar A.go, el compilador lee Bo no Co A escala, esto puede ser una gran aceleración de ".
OK, la tangente se hace ligera. ¿Por qué es eso relevante? La respuesta también está en el PDF de Go Tech Talk:
"Modelo de paquete: dependencias explícitas para permitir compilaciones más rápidas."
supongo que los desarrolladores Go tomaron la postura de que cuando los tiempos de compilación se miden en segundos, incluso en caso de grandes proyectos, que es más productivo para los desarrolladores para mantener tiempos de compilación que se corta. Digamos que me lleva 8 segundos recopilar 200,000 líneas de código y descubrir que tengo una importación de paquete extraño, 5-10 segundos (con un IDE bueno o una buena familiaridad con su entorno de desarrollo) para encontrarlo y solucionarlo, y otros 8 segundos para recompilar. Llámalo 30 segundos en total, y ahora todas mis compilaciones futuras permanecen en el rango de 10 segundos. O podemos dejar que nuestro módulo crezca al incluir dependencias innecesarias, y observar que el tiempo de compilación aumenta de 8 a 10, 12 o 15 segundos. No parece mucho porque todos estamos acostumbrados a compilar tiempos del orden de minutos, pero cuando comienzas a darte cuenta de que eso es una degradación del rendimiento del 25%, te paras a pensarlo un minuto.
Ir tiempos de compilación son ya la velocidad del rayo. Tenga en cuenta también que las velocidades del procesador siguen aumentando (si no tanto como en el pasado) y que el número de núcleos disponibles también está aumentando (y la compilación de grandes cantidades de código es muy adecuada para multihebras). Hoy, 200,000 líneas de código en 8 segundos significa que no es irracional imaginar 200,000 líneas de código compiladas de forma esencialmente instantánea en 10 años. Creo que el equipo de Go ha tomado una decisión consciente aquí para hacer que los tiempos de compilación sean cosa del pasado, y aunque el problema que usted menciona es solo una pequeña parte de eso, es y aún forma parte de eso.
En otra nota completamente, el equipo de Go también parece haber desarrollado una filosofía de diseño del lenguaje que obliga a algunas buenas prácticas de programación.Para su crédito, se han esforzado por lograrlo sin penalizaciones graves de rendimiento, y han tenido éxito en gran medida. [Aparte: las dos únicas cosas que puedo pensar de forma directa que impactan en el rendimiento son la recolección de basura y las variables inicializadas a la fuerza - y esto último es bastante trivial en este día y edad.] Esto va a irritar a algunos programadores, mientras hace felices a otros . Es un viejo y viejo argumento en el mundo de la programación, y está bastante claro en qué lado se ha basado Go, le guste o no.
Creo que las dos fuerzas juntas influyeron en su decisión, y creo que al final del día es un buen camino a seguir, aunque apoyo a otros comentaristas que sugirieron permitir una bandera "--strict" o alguna para hacer que este comportamiento particular sea opcional, particularmente durante las primeras etapas del ciclo de vida de un proyecto. Me pude ver fácilmente definiendo variables o incluyendo paquetes cuando empiezo a escribir código que sé que necesitaré más tarde, aunque todavía no he escrito el código que los necesita.
+1 para el diseño basado en IDE. Llegué a la misma conclusión, principalmente por el hecho de que solo los archivos objeto tienen algo parecido a un encabezado, y también que Go incluye módulos para analizar Go. –