Предыдущая статьяПредставлена установка Golang под разные системы, и классический кейс Hello World завершен. В этом процессе мы использовали команду go run, которая завершает весь процесс от компиляции до выполнения исходного кода.
Сегодня мы подробно опишем этот процесс. Простое понимание, запуск может быть эквивалентен сборке + выполнение.
Краткое описание команды сборки
В Golang процесс сборки в основном выполняется командой go build. Он завершает компиляцию исходного кода и генерацию исполняемого файла.
go build получает параметры в виде файлов .go или каталогов и по умолчанию компилирует все файлы .go в текущем каталоге. Выполнение под основным пакетом создаст соответствующий исполняемый файл.Под неосновным пакетом он выполнит некоторые проверки.Сгенерированные файлы библиотеки помещаются в каталог кеша, а в рабочем каталоге новые файлы не генерируются.
Создать новый приветственный случай
Перед официальным введением в процесс компиляции давайте еще раз продемонстрируем кейс Hello World и создадим новый файл hello.go.Код выглядит следующим образом:
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
Выполните команду go build hello.go, чтобы сгенерировать исполняемый файл hello в каталоге. Выполните hello и выведите Hello World.
Представляем варианты сборки
Демонстрация процесса компиляции требует помощи нескольких опций, предоставляемых go build, и выполните go help build для просмотра. следующим образом:
$ go help build
...
-n 不执行地打印流程中用到的命令
-x 执行并打印流程中用到的命令,要注意下它与-n选项的区别
-work 打印编译时的临时目录路径,并在结束时保留。默认情况下,编译结束会删除该临时目录。
...
Эти параметры также применяются к команде go run. Как вы думаете, это похоже на опцию команды sh, видно, что многие знания в компьютере одинаковы.
поток выполнения печати
Используйте параметр -n, чтобы просмотреть ход выполнения go build без выполнения команды, как показано ниже:
$ go build -n hello.go
#
# command-line-arguments
#
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/polo/Public/Work/go/src/study/basic/hello
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath $WORK/b001 -p main -complete -buildid fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye -goversion go1.11.1 -D _/Users/polo/Public/Work/go/src/study/basic/hello -importcfg $WORK/b001/importcfg -pack -c=4 ./hello.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
...
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=P1Y_fbNXAEG6zEEGqFsM/fVbBEz0nTJc3r6VxU5ye/fVbBEz0nTJc3r6VxU5ye/P1Y_fbNXAEG6zEEGqFsM -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out hello
Процесс выглядит очень сумбурно, и если приглядеться, то видно, что в основном он состоит из нескольких частей, а именно:
- Создайте временный каталог, mkdir -p $WORK/b001/;
- Найти информацию о зависимости, cat >$WORK/b001/importcfg
- Выполнить компиляцию исходного кода, /usr/local/go/pkg/Tool/Darwin_AMD64/Compile...
- Собрать файлы библиотеки ссылок, cat >$WORK/b001/importcfg.link
- Сгенерировать исполняемый файл, /usr/local/go/pkg/tool/darwin_amd64/link -o ...;
- Переместите исполняемый файл, mv $WORK/b001/exe/a.out hello;
С этим объяснением процесс сборки становится очень понятным. Если вы знакомы с разработкой на C/C++, этот процесс покажется вам знакомым. Конечно, в отличие от этого, c/c++ будет иметь еще один этап предварительной обработки.
Затем оптимизируйте предыдущую блок-схему следующим образом:
Уточняем процесс сборки на две части, compile and link, то есть компилируем и связываем. Здесь используются две очень важные команды: complie и link. Все они являются подкомандами инструмента go.
Расскажите о процессе бега
После понимания процесса сборки запустить его легко. Мы используем go run -x hello.go для просмотра процесса выполнения следующим образом:
...
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/hello -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=fveq2guPMmsyv8t4cV_M/xYBkVZeN1BHy2ygmstrB/pWJerx2-jOU98BpvIFO6/fveq2guPMmsyv8t4cV_M -extld=clang $WORK/b001/_pkg_.a
$WORK/b001/exe/hello
Hello World
Сосредоточьтесь на конечной части В отличие от сборки, после того, как ссылка сгенерирует файл hello, он не перемещает его в текущий каталог, а выполняет программу через $WORK/b001/exe/hello. При компиляции рисуется следующая блок-схема:
На данный момент весь процесс запуска очень ясен.
Pass --work, чтобы сохранить исполняемые файлы
Так можно ли получить этот временно сгенерированный исполняемый файл? Значение по умолчанию неприемлемо, временный каталог будет удален в конце запуска. Мы можем сохранить этот каталог с --work. Процесс демонстрации выглядит следующим образом:
$ go run -x --work hello.go
WORK=/var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400
...
$WORK/b001/exe/hello
Hello World
После печати пути к временному каталогу WORK мы можем скопировать файл приветствия, сгенерированный run, в текущий каталог с помощью команды mv, как показано ниже:
$ mv /var/folders/bw/8yw8h4yj2vb6mxtb6t8t41f00000gn/T/go-build149627400b001/exe/hello hello
Вы можете выполнить hello, чтобы убедиться, что это то, что мы ожидали.
Суммировать
В этой статье представлен процесс компиляции и выполнения Golang из go run. Используя несколько вариантов отладки, предоставляемых сборкой, мы реализовали пошаговую декомпозицию процесса и, наконец, подробно представили каждый этап всего процесса компиляции и выполнения.