Недавно я обнаружил проблему при написании небольшого проекта. Сначала смоделируйте сцену моего демо:
Проще говоря, существует демо-версия, состоящая из двух файлов go.,соответственнодаhello.go
иmain.go
,вmain.go
вmain
Функция требует ссылкиhello.go
вprintHello()
функция,Но дасуществовать неожиданно сообщил об ошибке при компиляции проекта.,Взаимосвязь между кодом и файлами следующая:
Отношения файлов:
├── go.mod
├── hello.go
└── main.go
hello.go
package main
import "fmt"
func printHello() {
fmt.Println("Hello ...")
}
main.go
package main
func main() {
printHello()
}
Далее я хочу скомпилировать эту демо-версию в исполняемый файл.,Когда я используюgo build main.go
Об ошибке было сообщено, когда,следующее:
# command-line-arguments
./main.go:4:5: undefined: printHello
Эта ошибка указывает на то, что определение функции printHello не может быть найдено в main.go, но субъективно мы должны думать, что она может найти эту функцию. Ведь они все находятся в одном каталоге, просто разные файлы, но скомпилировать их невозможно. , поэтому я использовал команду go build, и она оказалась успешной. Позже я проверил команду go build и обнаружил, что она содержит много знаний!
go build
Команда Go язык, предоставленный для компиляции Go Программные инструменты. Когда ты бежишь go build
, он будет искать файлы в текущем каталоге или указанном каталоге .go
файлы исходного кода, скомпилировать их и сгенерировать исполняемые файлы (в формате Windows Да .exe
файл, в Unix-like Системные файлы без расширения). По умолчанию имя созданного исполняемого файла содержит main
Имя пакета функции такое же (но обычно оно первое в вашем каталоге). .go
Имя пакета файла, если вы явно не укажете имя выходного файла в командной строке).
go build
Основное использование команды следующее:
go build [options] [packages]
options
:Дополнительные параметры компиляции,Используется для управления процессом компиляции. Например,-o
Опции позволяют указать имя выходного файла.packages
:Список имен пакетов для компиляции。Если опущено,go build
Скомпилирует все файлы в текущем каталоге и его подкаталогах. .go
документ.1) Общие варианты
-o file
:Укажите имя выходного файла。если не указано,Имя выходного файла по умолчанию соответствует имени пакета.(Первое не _
начало .go
Пакетное имя файла существует).-i
:Установите зависимые пакеты, но не компилируйте целевой код.。этот вариантсуществовать Go 1.11 и более поздние версии устарели, поскольку существуют go build
Зависимости будут автоматически установлены по мере необходимости.-v
:Распечатайте имя пакета, скомпилированное в процессе компиляции.。-work
:Печатает путь к временному рабочему каталогу, используемому для компиляции.(но, пожалуйста, обратите внимание,.o
Файлы еще можно очистить).-x
:Распечатайте конкретные выполненные команды,Включает команды, используемые во время компиляции и компоновки.2) Пример
Скомпилируйте программу Go в текущем каталоге:
go build
Это создаст исполняемый файл в текущем каталоге (имя файла основано на имени пакета).
Укажите имя выходного файла:
go build -o myapp
Это создаст файл с именем myapp
исполняемый файл (в формате Unix-like система) или myapp.exe
(существовать Windows начальство).
Скомпилируйте конкретный пакет:
go build github.com/user/repo
Это скомпилирует указанный репозиторий (GitHub на user/repo
)в Go программу и генерирует исполняемый файл (если пакет содержит main
функция). Однако обратите внимание, что если вы не запустите эту команду из корня репозитория, полученный исполняемый файл обычно будет помещен в ваш GOPATH/bin
каталог (если вы установили GOPATH
) или в текущем каталоге (если вы используете Go Модули, а не ставить GOPATH
)。
3) Внимание
go build
命令不会输出编译过程в错误信息到标准输出(stdout),И выводит их в стандартную ошибку (stderr). Это означает, что вы можете получить результаты компиляции, перенаправив стандартный вывод,не путаясь с сообщениями об ошибках.go build
будет основано на go.mod
файл для компиляции вашей программы и автоматической загрузки недостающих зависимостей.go build
Никакая подробная информация о процессе компиляции не будет выведена, если вы не используете -v
или -x
параметры.go build
команда и go build main.go
Команда находится в Go язык для компиляции Go процедуры, но между ними есть некоторые ключевые различия, в первую очередь связанные с Go Структура пакета и область компиляции.
1)go build
когда содержит только main
запустить в каталоге пакета (или его родительском каталоге) go build
Приказывая, Иди Инструментальная цепочка будет искать все файлы в текущем каталоге (и его подкаталогах). .go
файл для создания двоичного исполняемого файла, содержащего все соответствующие зависимости. Имя этого двоичного файла по умолчанию совпадает с именем текущего каталога (но с удалением всех возможных разделителей путей) и не содержит .go
суффикс. Например, если ваш каталог называется myapp
,и каталогили其子目录中包含 main
пакет, затем go build
сгенерирует файл с именем myapp
(или myapp.exe
существовать Windows выше) исполняемый файл.
2)go build main.go
когда ты используешь go build main.go
Приказывая, Иди 工具链的行为会有所不同。это будет main.go
файл рассматривается как отдельная единица компиляции, и попытки предпринимаются только на основе main.go
Файл для импорта пакета непосредственно для сборки программы. Это означает, что если main.go
Зависит от других в текущем каталоге или других каталогах .go
файлы, но эти зависимости не прошли import
заявлениесуществовать main.go
Явно представлено в,тогда эти зависимости могут не быть включены в окончательный двоичный файл,Это может вызвать ошибки компиляции и ошибки выполнения.
Кроме того, используйте go build main.go
Когда имя сгенерированного двоичного файла может быть основано на main.go
Все имена каталогов существуют, а не даны. main.go
Содержимое файла или имя пакета внутри него. Однако конкретные варианты поведения могут различаться в зависимости от Go Различные версии и конкретные среды.
в целом,Рекомендуется go build
,потому что это следует Go Принцип управления пакетами позволяет автоматически обрабатывать все связанные файлы в текущем каталоге и его подкаталогах. .go
документ,Убедитесь, что все зависимости включены правильно。избегайте использования go build main.go
,Если вам действительно не нужно скомпилировать только main.go
файл и убедитесь, что он содержит все необходимые зависимости. Как правило, такое использование не рекомендуется, поскольку оно может игнорировать важный код и зависимости, что приведет к нестабильной работе программ или неожиданным ошибкам компиляции.
На этом этапе мы, вероятно, понимаем,Потому что существование использует файл main.go только при использовании go build main.go.,Итак, как мы можем улучшить? Ответ — скомпилировать связанные файлы вместе.:
go build -o demo main.go hello.go
В этом случае компиляция пройдет успешно~
Фактически, с макроэкономической точки зрения,Процесс компиляции практически всех языков программирования высокого уровня (Java, C, Go, C++ и т. д.) одинаков,По сути, он включает в себя процессы лексического анализа, синтаксического анализа, семантического анализа, генерации промежуточного кода, оптимизации целевого кода и связывания.,Только использование дакомпилятора разное.
1) Лексический анализ Analysis) : Разложить исходный код на токены. Теги — это основные единицы исходного кода, такие как идентификаторы, ключевые слова, операторы, разделители и т. д. Lexer использует регулярные выражения для идентификации последовательностей символов в исходном коде и преобразования их в токены. Эти токены затем передаются анализатору.
2) Синтаксис Analysis) : Объедините лексемы, сгенерированные на этапе лексического анализа, в грамматические структуры (например, выражения, утверждения, функции и т. д.). Анализатор использует контекстно-свободную грамматику (CFG) для анализа этих токенов и построения абстрактного синтаксического дерева (AST). AST — это древовидное представление исходного кода, отражающее грамматическую структуру программы.
3) Семантический анализ (Семантический Analysis) : Проверить смысловую правильность грамматических конструкций.,Включая проверку типов, вывод типов, встраивание функций и другие работы по оптимизации. существовать на этом этапе,компилятор проверит типобезопасность кода,Убедитесь, что все переменные и выражения имеют правильный тип. также,Gocompilator также выполняет вывод типа.,Для переменных, инициализированных с использованием литералов,компилятор автоматически определяет его тип. в то же время,компилятор также оптимизирует код,Например, встраивание функций,Чтобы уменьшить накладные расходы на вызовы функций.
4) Генерация промежуточного кода (Код Generation): Воля Семантический Синтаксическая структура после анализа преобразуется в машинный код или промежуточный код (IR). существовать на этом этапе,компилятор преобразует AST в представление более низкого уровня.,Обычно да промежуточный код (IR). Промежуточный код да Представление кода, независимое от платформы,Легче преобразовать в машинный код для разных платформ. Затем,компилятор преобразует промежуточный код в машинный код для целевой платформы.
5) Оптимизация целевого кода (Цель Code Optimization) :существовать в некоторых случаях,существование компилятора может быть дополнительно оптимизировано после генерации целевого кода.,Повысить эффективность выполнения целевого кода.
6) Связывание :Воля多个编译单元(как несколько.o
документ)и必要的库документ链接成一个可执行документ.компоновщик(Linker)会处理所有编译生成的机器代码документ,и любые файлы библиотеки, необходимые программе,Объедините их в один исполняемый файл. Этот исполняемый файл содержит все инструкции и данные, необходимые для запуска программы.
в,Лексический анализ, синтаксический анализ и семантический анализ относятся к интерфейсу компиляции, а остальные относятся к серверной части компиляции.
Интерфейс компиляции является первым этапом работы компилятора и в основном отвечает за обработку лексического и синтаксического анализа исходного кода, а также за генерацию промежуточных представлений (таких как промежуточный код или абстрактные синтаксические деревья). Это критический шаг в преобразовании исходного кода в промежуточную форму, которая может быть обработана компилятором внутри страны.
Серверная часть компиляции — это второй этап компилятора, который в основном отвечает за оптимизацию кода и генерацию целевого кода. Он оптимизирует код на основе промежуточного представления, сгенерированного внешним интерфейсом, и, наконец, генерирует код машинного языка для целевой машины.
Интерфейсная часть отвечает за лексический и синтаксический анализ исходного кода, а также за генерацию промежуточных представлений; внутренняя часть отвечает за оптимизацию кода и генерацию целевого кода; Тесное сотрудничество между ними обеспечивает плавный процесс компиляции и эффективное выполнение окончательно сгенерированного кода.
go build да Go Очень мощная и гибкая команда языка, которая делает преобразование исходного кода в исполняемые файлы простым и понятным. Воспользовавшись его различными опциями и возможностями кроссплатформенной компиляции, вы можете легко компилировать и распространять свои Go программа. Независимо от того, находится ли дасуществовать в процессе разработки или дасуществовать готово к развертыванию, иди build Да Go Неотъемлемая часть инструментария программиста.
В то же время Принцип Составление действительно является курсом, заслуживающим углубленного изучения. Он не только закладывает важный краеугольный камень информатики на теоретическом уровне, но и демонстрирует его незаменимую ценность в практических приложениях. Изучая Принцип составления,Мы можем систематически осваивать принципы проектирования языков программирования, методы построения и методы оптимизации компилятора.,Это имеет большое значение для улучшения навыков программирования, понимания основного механизма работы компьютерных систем и проведения эффективной разработки программного обеспечения.