Я предполагаю, что самая большая мотивация для этого и самый большой результат, это улучшение во время компиляции. Предварительный видеоролик о технических новостях продемонстрировал их способность компилировать большие объемы кода за короткие промежутки времени (их пример - 200 000 строк кода за 8 секунд на MacBook - без каких-либо технических характеристик машины).
Также в техническом видео они особо отмечают, что одним из самых больших достижений, которые они достигли, было изменение компиляции и связывания модулей.
Вот пример того, как что-то будет работать в текущей системе C / C ++:
Класс A определен в заголовочном файле C_H и реализован в C_CPP.
Класс B наследуется от C и реализован в файлах B_H и B_CPP.
Класс A является производным от B и реализован в файлах A_H и A_CPP.
Из-за цепочек деривации A_CPP включает в себя A_H, B_H и C_H. B_CPP включает в себя B_H и C_H. C_CPP включает в себя C_H. Из-за природы препроцессора C, который по существу превращает #include в операцию вырезания и вставки, содержимое C_H запускается через компилятор 3 раза, а B_H - дважды.
Кроме того, все содержимое A_CPP, B_CPP и C_CPP находится в своих собственных объектных файлах. Следовательно, когда компоновщик отправляется для разрешения A.o, он вынужден загружать и обрабатывать как B.o, так и C.o. Кроме того, когда он разрешает B.o, он должен снова обработать C.o.
Предварительно скомпилированные заголовки могут немного помочь с первой частью этой проблемы, но они также могут быть непростой задачей, и я знаю многих разработчиков, которые просто не используют их по этой причине. Это также принципиально не меняет проблему - заголовки по-прежнему обрабатываются на нескольких уровнях несколько раз, только теперь вместо исходного кода обрабатывается предварительно скомпилированный двоичный файл. Вырезаны несколько шагов, но не весь процесс.
Го подходит к вещам по-другому. В словах прямо из PDF из их технической беседы :
"Компилятор Go тянет переходный
информация о типе зависимости от объекта
файл - но только то, что ему нужно. Если А.го
зависит от B.go зависит от C.go:
- составить C.go, B.go, затем A.go.
- для компиляции A.go, компилятор читает B.o, а не C.o. В масштабе это может быть огромным
ускорив. "
ОК, небольшая касательная выполнена. Почему это актуально? Ответ также есть в Go Tech Talk PDF:
"Модель пакета: явные зависимости
чтобы ускорить сборку. "
Я предполагаю, что разработчики Go придерживались той позиции, что когда время компиляции измеряется в секундах, даже для очень больших проектов, для разработчиков более продуктивно сохранять время компиляции таким коротким. Скажем, мне нужно 8 секунд, чтобы скомпилировать 200 000 строк кода и обнаружить, что у меня есть посторонний импорт пакетов, 5-10 секунд (с хорошей IDE или хорошим знакомством с вашей средой разработки), чтобы найти и исправить это, и еще 8 секунд для перекомпиляции. Назовите это всего 30 секунд - и теперь все мои будущие компиляции остаются в диапазоне 10 секунд. Или мы можем позволить нашему модулю расти за счет включения ненужных зависимостей и наблюдать, как время компиляции увеличивается с 8 до 10, 12 или 15 секунд. Это не так много, потому что мы все привыкли компилировать время порядка минут - но когда вы начинаете понимать, что это снижение производительности на 25%, вы останавливаетесь и думаете об этом минуту.
Время компиляции Go уже молниеносно. Также учтите, что скорости процессора все еще увеличиваются (если не так сильно, как в прошлом) и что число доступных ядер также увеличивается (а компиляция больших объемов кода хорошо подходит для многопоточности). 200 000 строк кода за 8 секунд сегодня означают, что не исключено, что 200 000 строк кода будут компилироваться практически мгновенно за 10 лет. Я думаю, что команда Go приняла здесь осознанное решение сделать время компиляции делом прошлого, и хотя проблема, о которой вы говорите, является лишь малой ее частью, она является все еще частью этой проблемы. .
В заключение отметим, что команда Go также, похоже, разработала философию языкового дизайна, которая стимулирует некоторые хорошие практики программирования. К их чести, они приложили усилия, чтобы добиться этого без серьезных потерь производительности, и в основном добились успеха. [В сторону: единственные две вещи, которые я могу придумать, что на самом деле влияет на производительность, это сборка мусора и принудительно инициализированные переменные - и последнее довольно тривиально в наше время.] Это будет по-королевски раздражать некоторых программистов, а других радовать , Это старый, старый аргумент в мире программирования, и совершенно ясно, на какую сторону пошёл Go, нравится вам это или нет.
Я думаю, что две силы вместе повлияли на их решение, и я думаю, что в конце дня это хороший путь, хотя я поддерживаю других комментаторов, которые предложили разрешить флаг "--strict" или что-то подобное сделать это поведение необязательным, особенно на ранних этапах жизненного цикла проекта. Я легко мог видеть, как определяю переменные или включаю пакеты, когда впервые начинаю писать код, который, как я знаю, понадобится мне позже, хотя я еще не написал код, который нуждается в них.