Go程序编译
1. 交叉编译(Cross compiler)
“ 交叉编译是在一个平台上生成另一个平台上的可执行代码。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行 ”
对于交叉编译我们简单的理解是在当前平台上编译出其他平台可以执行的文件
交叉编译给我们带来的好处是我们一次编写的代码经过交叉编译之后可以在多个平台上执行
我们在
Windows
编写Go程序可以编译成在Mac OS
或者Linux
上的运行程序 (良好的可移植性)
2. 交叉编译设置
重点参数说明 :
GOOS : 目标操作系统
GOARCH : 目标操作系统的架构
1.1 Windows 平台
# 目标平台 MacSET GOOS=darwin SET GOARCH=amd64
# 执行编译go build main.go
# 目标平台 LinuxSET GOOS=linuxSET GOARCH=amd64go build main.go
1.2 Linux 平台
# 目标平台 MacCGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
# 目标平台 WindowsCGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
1.3 Mac 平台
# 目标平台 LinuxCGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
# 目标平台 windowsCGO_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 listaix/ppc64android/386android/amd64android/armandroid/arm64darwin/386darwin/amd64darwin/armdarwin/arm64dragonfly/amd64freebsd/386freebsd/amd64freebsd/armjs/wasmlinux/386linux/amd64linux/armlinux/arm64linux/mipslinux/mips64linux/mips64lelinux/mipslelinux/ppc64linux/ppc64lelinux/s390xnacl/386nacl/amd64p32nacl/armnetbsd/386netbsd/amd64netbsd/armopenbsd/386openbsd/amd64openbsd/armplan9/386plan9/amd64plan9/armsolaris/amd64windows/386windows/amd64windows/arm
3. 编译简单示例 :
Windows 平台编译 Linux 运行程序
G:\app_project\GoProject>set GOOS=linux
G:\app_project\GoProject>go envset GOARCH=amd64set GOBIN=set GOCACHE=C:\Users\captain\AppData\Local\go-buildset GOEXE=set GOFLAGS=set GOHOSTARCH=amd64set GOHOSTOS=windowsset GOOS=linuxset GOPATH=E:\Goset GOPROXY=https://goproxy.cnset GORACE=set GOROOT=C:\GOset GOTMPDIR=set GOTOOLDIR=C:\GO\pkg\tool\windows_amd64set GCCGO=gccgoset CC=gccset CXX=g++set CGO_ENABLED=0set GOMOD=set CGO_CFLAGS=-g -O2set CGO_CPPFLAGS=set CGO_CXXFLAGS=-g -O2set CGO_FFLAGS=-g -O2set CGO_LDFLAGS=-g -O2set PKG_CONFIG=pkg-configset 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-switchesG:\app_project\GoProject\>go build main.go
将生成的可执行文件main
上传到 Linux服务器上
# 进入main所在位置
# 给main程序可执行权限chmod +x main
# 执行./main
Go程序部署
1. 容器部署
容器部署是现在比较流行的部署方式,容器部署的前提是服务器上安装了
Docker
基础步骤:
- 编译程序
- 编写Dockerfile
- 通过Dockerfile 编译成docker镜像
- 通过新建的镜像运行一个Golang程序容器
# 将Golang程序编译成对应平台的可执行文件 (-o 指定名称)GOOS=linux GOARCH=amd64 go build -o MyApp main.go
# 如果是windows平台生成可执行文件SET GOOS=linuxSET GOARCH=amd64go build -o MyApp main.go
# 新建 Dockerfile (linux平台执行) touch Dockerfile
# 要是windows 平台就新建一个文件文件名就是Dockerfile(没有文件后缀)
1.1 编写Dockerfile (简单示例文件)
# 镜像是基于alpine:3.8FROM loads/alpine:3.8
# LABLE 给镜像添加元数据# MAINTAINER 维护者信息LABEL maintainer="demo@163.com"
# ENV 指定环境变量
# 设置固定的项目路径ENV WORKDIR /var/wwwroot/BossAdmin
# ADD <src> <dest> 复制指定的 <src> 到容器中的 <dest>
# MyApp是Go代码生成的可执行文件ADD ./MyApp $WORKDIR/main
# RUN 指令将在当前镜像基础上执行指定命令
# 添加应用可执行文件,并设置执行权限RUN chmod +x $WORKDIR/main
# 添加静态文件、配置文件、模板文件 (根据自己的项目实际情况配置)ADD public $WORKDIR/publicADD configs $WORKDIR/configsADD templates $WORKDIR/templates
# EXPOSE docker容器暴露的端口EXPOSE 8080
# 指定工作目录WORKDIR $WORKDIR
# CMD 指定启动容器时执行的命令CMD ./main
1.2 通过新建的Dockerfile创建镜像
命令
docker build
创建镜像命令格式
docker build [选项] 路径
参数
-t
来指定镜像的标签
看一下当前文件结构
[root@host5 MyApp]# lltotal 21552drwxr-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 MyAppdrwxr-xr-x. 2
root root 6 May 12 03:22 publicdrwxr-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.07MBStep 1/11 : FROM loads/alpine:3.8 ---> 20aa4fd1c5a8Step 2/11 : LABEL maintainer="demo@163.com" ---> Running in da0bed8c5bb5Removing intermediate container da0bed8c5bb5 ---> 5a5500648739Step 3/11 : ENV WORKDIR /var/wwwroot/BossAdmin ---> Running in 13156e7b009cRemoving intermediate container 13156e7b009c ---> bcde11586009Step 4/11 : ADD ./MyApp $WORKDIR/main ---> fb1a6391b87fStep 5/11 : RUN chmod +x $WORKDIR/main ---> Running in 75d29f00223dRemoving intermediate container 75d29f00223d ---> 7e1cd9f4a222Step 6/11 : ADD public $WORKDIR/public ---> 56d02d9b71a1Step 7/11 : ADD configs $WORKDIR/configs ---> ec60ca235b75Step 8/11 : ADD templates $WORKDIR/templates ---> a0607eee6429Step 9/11 : EXPOSE 8080 ---> Running in fce1a3f02e70Removing intermediate container fce1a3f02e70 ---> 95cbaaae1b85Step 10/11 : WORKDIR $WORKDIR ---> Running in f1b15db866e3Removing intermediate container f1b15db866e3 ---> ac7b91d386b3Step 11/11 : CMD ./main ---> Running in 750d968533baRemoving intermediate container 750d968533ba ---> 28da775342b1Successfully built 28da775342b1Successfully tagged app1:latest[root@host5 MyApp]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEapp1 latest 28da775342b1 51 seconds ago 55MB[root@host5 MyApp]
# docker run -it app1 /bin/bash bash-4.4
# ls -ltotal 21548drwxr-xr-x 2 root root 46 May 13 09:54 configs-rwxr-xr-x 1 root root 22062544 May 12 15:22 maindrwxr-xr-x 2 root root 6 May 13 09:54 publicdrwxr-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程序在后台执行即可 (当前环境是 : CentOS7)
让Go程序后台执行的方式挺多的,简单罗列一下,具体使用也不麻烦.
2.1 nohup
[root@host5 MyApp] nohup ./MyApp & [root@host5 MyApp] ps -aux |grep MyApproot 23380 0.0 0.2 118908 10796 pts/0 Sl 06:52 0:00 ./MyApproot 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 # 如果没有安装就执行该命令[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# 执行的命令command=/data/wwwwroot/BossAdmin/MyApp# 日志输出stdout_logfile=/data/wwwwlog/app1/app1-stdout.logstderr_logfile=/data/wwwwlog/app1/app1-stderr.log# supervisor启动的时候是否随着同时启动,默认Trueautostart=true# 当程序exit的时候是否重启autorestart=true
supervisor 命令
supervisorctl status //查看所有进程的状态supervisorctl stop app1 //停止app1supervisorctl start app1 //启动app1supervisorctl restart app1 //重启app1supervisorctl 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 # 程序执行的目录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 # 查看服务运行状态 [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.jpg1 directory, 3 files
编写
nginx
配置文件更具场景配置文件会有不同
示例配置文件名 :
GoApp.conf
server {
# 监听的端口
listen
18080;
# 域名
server_name _ ;
# 访问日志
access_log /data/wwwlogs/GoApp1-access.log;
# 错误日志
error_log /data/wwwlogs/GoApp1-error.log;
# 静态文件交给nginx处理,这里是采用文件后缀来区分的
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;
}
# 也可根据文件夹目录区分,指定目录的访问交给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 oknginx: 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"}}
静态文件处理
直接在客户端浏览器中访问