Go程序編譯
1. 交叉編譯(Cross compiler)
“ 交叉編譯是在一個平臺上生成另一個平臺上的可執(zhí)行代碼檐嚣。同一個體系結構可以運行不同的操作系統(tǒng)资昧;同樣居夹,同一個操作系統(tǒng)也可以在不同的體系結構上運行 ”
對于交叉編譯我們簡單的理解是在當前平臺上編譯出其他平臺可以執(zhí)行的文件
交叉編譯給我們帶來的好處是我們一次編寫的代碼經(jīng)過交叉編譯之后可以在多個平臺上執(zhí)行
我們在
Windows
編寫Go程序可以編譯成在Mac OS
或者Linux
上的運行程序 (良好的可移植性)
2. 交叉編譯設置
重點參數(shù)說明 :
GOOS : 目標操作系統(tǒng)
GOARCH : 目標操作系統(tǒng)的架構
1.1 Windows 平臺
# 目標平臺 Mac
SET GOOS=darwin
SET GOARCH=amd64
# 執(zhí)行編譯
go build main.go
# 目標平臺 Linux
SET GOOS=linux
SET GOARCH=amd64
go build main.go
1.2 Linux 平臺
# 目標平臺 Mac
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
# 目標平臺 Windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
1.3 Mac 平臺
# 目標平臺 Linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
# 目標平臺 windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
tips1 :
交叉編譯是不支持
CGO
的(Go代碼中存在C代碼是編譯不過的) , 所以需要將CGO_ENABLED
設置為0 (禁用CGO
)需要支持
CGO
就要將CGO_ENABLED
設置為1tips2 :
我們通過如下命令查看Go支持OS和平臺列表
$ go tool dist list aix/ppc64 android/386 android/amd64 android/arm android/arm64 darwin/386 darwin/amd64 darwin/arm darwin/arm64 dragonfly/amd64 freebsd/386 freebsd/amd64 freebsd/arm js/wasm linux/386 linux/amd64 linux/arm linux/arm64 linux/mips linux/mips64 linux/mips64le linux/mipsle linux/ppc64 linux/ppc64le linux/s390x nacl/386 nacl/amd64p32 nacl/arm netbsd/386 netbsd/amd64 netbsd/arm openbsd/386 openbsd/amd64 openbsd/arm plan9/386 plan9/amd64 plan9/arm solaris/amd64 windows/386 windows/amd64 windows/arm
3. 編譯簡單示例 :
Windows 平臺編譯 Linux 運行程序
G:\app_project\GoProject>set GOOS=linux
G:\app_project\GoProject>go env
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\captain\AppData\Local\go-build
set GOEXE=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=linux
set GOPATH=E:\Go
set GOPROXY=https://goproxy.cn
set GORACE=
set GOROOT=C:\GO
set GOTMPDIR=
set GOTOOLDIR=C:\GO\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-fPIC -m64 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\captain\AppData\Local\Temp\go-build187358654=/tmp/go-build -gno-record-gcc-switches
G:\app_project\GoProject\>go build main.go
將生成的可執(zhí)行文件main
上傳到 Linux服務器上
# 進入main所在位置
# 給main程序可執(zhí)行權限
chmod +x main
# 執(zhí)行
./main
Go程序部署
1. 容器部署
容器部署是現(xiàn)在比較流行的部署方式,容器部署的前提是服務器上安裝了
Docker
基礎步驟:
- 編譯程序
- 編寫Dockerfile
- 通過Dockerfile 編譯成docker鏡像
- 通過新建的鏡像運行一個Golang程序容器
# 將Golang程序編譯成對應平臺的可執(zhí)行文件 (-o 指定名稱)
GOOS=linux GOARCH=amd64 go build -o MyApp main.go
# 如果是windows平臺生成可執(zhí)行文件
SET GOOS=linux
SET GOARCH=amd64
go build -o MyApp main.go
# 新建 Dockerfile (linux平臺執(zhí)行)
touch Dockerfile
# 要是windows 平臺就新建一個文件文件名就是Dockerfile(沒有文件后綴)
1.1 編寫Dockerfile (簡單示例文件)
# 鏡像是基于alpine:3.8
FROM loads/alpine:3.8
# LABLE 給鏡像添加元數(shù)據(jù)
# MAINTAINER 維護者信息
LABEL maintainer="demo@163.com"
# ENV 指定環(huán)境變量
# 設置固定的項目路徑
ENV WORKDIR /var/wwwroot/BossAdmin
# ADD <src> <dest> 復制指定的 <src> 到容器中的 <dest>
# MyApp是Go代碼生成的可執(zhí)行文件
ADD ./MyApp $WORKDIR/main
# RUN 指令將在當前鏡像基礎上執(zhí)行指定命令
# 添加應用可執(zhí)行文件,并設置執(zhí)行權限
RUN chmod +x $WORKDIR/main
# 添加靜態(tài)文件管行、配置文件厨埋、模板文件 (根據(jù)自己的項目實際情況配置)
ADD public $WORKDIR/public
ADD configs $WORKDIR/configs
ADD templates $WORKDIR/templates
# EXPOSE docker容器暴露的端口
EXPOSE 8080
# 指定工作目錄
WORKDIR $WORKDIR
# CMD 指定啟動容器時執(zhí)行的命令
CMD ./main
1.2 通過新建的Dockerfile創(chuàng)建鏡像
命令
docker build
創(chuàng)建鏡像命令格式
docker build [選項] 路徑
參數(shù)
-t
來指定鏡像的標簽
看一下當前文件結構
[root@host5 MyApp]# ll
total 21552
drwxr-xr-x. 2 root root 46 May 12 03:22 configs
-rw-r--r--. 1 root root 854 May 12 05:46 Dockerfile
-rw-r--r--. 1 root root 22062544 May 12 03:22 MyApp
drwxr-xr-x. 2 root root 6 May 12 03:22 public
drwxr-xr-x. 2 root root 6 May 12 03:22 templates
構建鏡像
[root@host5 MyApp]# docker build -t app1 .
Sending build context to Docker daemon 22.07MB
Step 1/11 : FROM loads/alpine:3.8
---> 20aa4fd1c5a8
Step 2/11 : LABEL maintainer="demo@163.com"
---> Running in da0bed8c5bb5
Removing intermediate container da0bed8c5bb5
---> 5a5500648739
Step 3/11 : ENV WORKDIR /var/wwwroot/BossAdmin
---> Running in 13156e7b009c
Removing intermediate container 13156e7b009c
---> bcde11586009
Step 4/11 : ADD ./MyApp $WORKDIR/main
---> fb1a6391b87f
Step 5/11 : RUN chmod +x $WORKDIR/main
---> Running in 75d29f00223d
Removing intermediate container 75d29f00223d
---> 7e1cd9f4a222
Step 6/11 : ADD public $WORKDIR/public
---> 56d02d9b71a1
Step 7/11 : ADD configs $WORKDIR/configs
---> ec60ca235b75
Step 8/11 : ADD templates $WORKDIR/templates
---> a0607eee6429
Step 9/11 : EXPOSE 8080
---> Running in fce1a3f02e70
Removing intermediate container fce1a3f02e70
---> 95cbaaae1b85
Step 10/11 : WORKDIR $WORKDIR
---> Running in f1b15db866e3
Removing intermediate container f1b15db866e3
---> ac7b91d386b3
Step 11/11 : CMD ./main
---> Running in 750d968533ba
Removing intermediate container 750d968533ba
---> 28da775342b1
Successfully built 28da775342b1
Successfully tagged app1:latest
[root@host5 MyApp]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
app1 latest 28da775342b1 51 seconds ago 55MB
[root@host5 MyApp]# docker run -it app1 /bin/bash
bash-4.4# ls -l
total 21548
drwxr-xr-x 2 root root 46 May 13 09:54 configs
-rwxr-xr-x 1 root root 22062544 May 12 15:22 main
drwxr-xr-x 2 root root 6 May 13 09:54 public
drwxr-xr-x 2 root root 6 May 13 09:54 templates
1.3 運行新鏡像
[root@host5 MyApp]docker run --name myapp1 -p 8080:8080 app1
Tips : 構建好的鏡像可以推送到(鏡像倉庫) 這樣其他位置需要使用的時候可以拉取鏡像
2. 獨立部署
如下操作都是在 Linux 平臺 (OS : Centos7)
獨立部署一般是在Linux平臺上部署Go程序 , 讓Go程序在后臺執(zhí)行即可 (當前環(huán)境是 : CentOS7)
讓Go程序后臺執(zhí)行的方式挺多的,簡單羅列一下,具體使用也不麻煩.
2.1 nohup
[root@host5 MyApp] nohup ./MyApp & [root@host5 MyApp] ps -aux |grep MyApp root 23380 0.0 0.2 118908 10796 pts/0 Sl 06:52 0:00 ./MyApp root 23390 0.0 0.0 112708 976 pts/1 S+ 06:52 0:00 grep --color=auto MyApp
2.2 tmux
[root@host5 MyApp] yum install -y tmux # 如果沒有安裝就執(zhí)行該命令 [root@host5 MyApp] tmux new -s MyApp #開啟新的會話窗口 [root@host5 MyApp] ./MyApp # 運行Go程序 [root@host5 MyApp] tmux attach -t MyApp # 進入之前的會話
2.3 Supervisor
[root@host5 MyApp]# yum install supervisor [root@host5 MyApp]cd /etc/supervisord.d [root@host5 MyApp]vim app1.ini
app1.ini
[program:app1] # 運行用戶身份 user=root # 執(zhí)行的命令 command=/data/wwwwroot/BossAdmin/MyApp # 日志輸出 stdout_logfile=/data/wwwwlog/app1/app1-stdout.log stderr_logfile=/data/wwwwlog/app1/app1-stderr.log # supervisor啟動的時候是否隨著同時啟動,默認True autostart=true # 當程序exit的時候是否重啟 autorestart=true
supervisor 命令
supervisorctl status //查看所有進程的狀態(tài) supervisorctl stop app1 //停止app1 supervisorctl start app1 //啟動app1 supervisorctl restart app1 //重啟app1 supervisorctl update //配置文件修改后使用該命令加載新的配置 supervisorctl reload //重新啟動配置中的所有程序
2.4 systemctl
我們很多服務可以使用
systemctl
來管理[root@host5 system]# pwd /etc/systemd/system [root@host5 system]# vim app1.service # 如下是app1.service 的內容 [Unit] # 單元描述 Description=MyApp [Service] Type=simple # 程序執(zhí)行的目錄 WorkingDirectory=/data/wwwwroot/BossAdmin/ # 啟動的腳本命令 ExecStart=/data/wwwwroot/BossAdmin/MyApp # 重啟條件 Restart=alway # 幾秒后重啟 RestartSec=5 [Install] WantedBy=multi-user.target
通過systemctl 啟動服務
[root@host5 system]# systemctl start app1 # 啟動服務 [root@host5 system]# systemctl restart app1 # 重啟服務 [root@host5 system]# systemctl status app1 # 查看服務運行狀態(tài) [root@host5 system]# systemctl stop app1 # 停止服務 [root@host5 system]# systemctl enable app1 # 添加為開機啟動項 [root@host5 system]# systemctl disable app1 # 從開機啟動項中移除
3. 代理部署
通常的做法是前置一個第三方的
web服務器
處理請求那么我們通常是使用
nginx
作為 這個前置層
部署實例
Linux服務器 (Centos7)
IP : 192.168.30.26
將Go項目上傳到Linux服務器的項目目錄下
[root@host2 GoApp1]# pwd
/data/wwwroot/GoApp1
[root@host2 GoApp1]# yum install -y tree
[root@host2 GoApp1]# tree
.
├── GoApp
└── public
├── anni.wav
└── go.jpg
1 directory, 3 files
編寫
nginx
配置文件更具場景配置文件會有不同
示例配置文件名 :
GoApp.conf
server {
# 監(jiān)聽的端口
listen 18080;
# 域名
server_name _ ;
# 訪問日志
access_log /data/wwwlogs/GoApp1-access.log;
# 錯誤日志
error_log /data/wwwlogs/GoApp1-error.log;
# 靜態(tài)文件交給nginx處理,這里是采用文件后綴來區(qū)分的
location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
access_log off;
expires 1d;
root /data/wwwroot/GoApp1/public;
try_files $uri @go_dispose;
}
# 也可根據(jù)文件夾目錄區(qū)分,指定目錄的訪問交給Nginx處理(將public目錄交給nginx處理)
# location ^~ /public {
# access_log off;
# expires 1d;
# root /data/wwwroot/GoApp1;
# try_files $uri @go_dispose;
# }
# 將其他程序交給后端Go處理
location / {
try_files $uri @go_dispose;
}
location @go_dispose {
# Go程序處理的地址
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
重啟nginx
[root@host2 vhost]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@host2 vhost]# service nginx restart
運行Go程序
[root@host2 GoApp1]# chmod +x GoApp
[root@host2 GoApp1]# ./GoApp
start http server and listen 8080
測試
后端Go程序處理
[root@host2 /]# curl -X POST -H "Content-type:application/json" -d '{"username":"admin","password":"123456","role":"edit"}' http://192.168.30.26:18080/auth
{"code":"200","message":"success","data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiZWRpdCIsImV4cCI6MTU4OTYyMDcxNywiaXNzIjoiY2FwdGFpbiIsInN1YiI6Imp3dCB0ZXN0In0.Ypqe9OP6yiIEqeo-Ub629kiEmYZVLnd8ZOh12R7BTns"}}
靜態(tài)文件處理
直接在客戶端瀏覽器中訪問
http://192.168.30.26:18080/go.jpg
能瀏覽到圖片
參考
- [1] golang交叉編譯和條件編譯的實際應用
- [2] tmux使用教程
- [3] Tmux 使用教程
- [4] Docker
- [5] Docker中文文檔
- [6] Systemd 入門教程:命令篇
- [7] Nginx文檔