ubuntu to windows

 


 
基础版本(推荐)
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o fibu.exe fibu2.go


极致压缩版本(使用 UPX)
# 先安装 UPX
sudo apt-get install upx

# 编译 + 压缩
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o myapp.exe main.go
upx --best myapp.exe  # 体积可减少 50-70%


带版本信息的发布版本
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build \
  -ldflags="-s -w -X main.Version=1.0.0 -X main.BuildTime=$(date +%Y%m%d)" \
  -o myapp.exe main.go

验证静态链接

 
在 Ubuntu 上检查(使用 file 和 ldd)
# 查看文件类型
file myapp.exe
# 输出:myapp.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows

# 检查依赖(静态编译应无外部依赖)
# 注意:ldd 对 Windows exe 无效,需到 Windows 或用 wine 测试


在 Windows 上验证 打开 PowerShell 或 CMD:powershell
# 查看依赖
dumpbin /dependents myapp.exe
# 静态编译后应只显示:KERNEL32.dll 等系统核心 DLL

# 或直接运行
myapp.exe


 


 
// "github.com/ThomasRooney/gexpect"
gexpect "github.com/google/goexpect"

go mod tidy 

剩下是修正对应的语法

推荐解决路径

 
首选:联系 gitee.com/tanpf/tools 维护者,建议替换为 github.com/google/goexpect(纯 Go)
次选:Fork 后自行修改,移除 expect 功能或使用条件编译
备选:如果 expect 是核心功能且必须保留,使用 mingw 编译并接受 DLL 依赖,或在 Linux 服务器端运行该功能

 
grep -r "gexpect" /ai/wks/gowks/src/tools/*

go mod graph | grep gexpect

 
# 安装 mingw-w64
sudo apt-get update
sudo apt-get install mingw-w64

# 使用 mingw 编译(注意:生成的 exe 会依赖 libgcc.dll)
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \
  go build -o fibu.exe fibu2.go

缺点:生成的 fibu.exe 需要携带 libgcc_s_seh-1.dll 和 libwinpthread-1.dll,不是纯静态


完全静态化(需额外参数):

 
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \
  go build -ldflags="-s -w -linkmode external -extldflags '-static'" \
  -o fibu.exe fibu2.go

带版本

 
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build \
  -ldflags="-s -w -X main.Version=1.0.0 -X main.BuildTime=$(date +%Y%m%d)" \
  -o myapp.exe main.go




 


 


 


go项目结构
### 现状:两种引入方式 同一个开发者的两个 gowks 工程,引入自己写的包用了两种完全不同的写法。 **方式一:fibu2.go(/ai/wks/gowks/src/cmd/fibu2,GOPATH 模式工程)** ```go import ( dcc "gitee.com/tanpf/gin/dc/client" // 带别名的完整"域名式"路径 "gitee.com/tanpf/tools" // 每个包都要带全命名空间 ) ``` **方式二:dws.go(/mnt/d/wks/gowks/src/cmd/edws,Go Modules 模式工程)** ```go import ( "gowks/dws" // 模块名 + 包路径,简洁 ) ``` 差异不在写法本身,而在工程采用的是 GOPATH 模式还是 Go Modules 模式: | 对比项 | 方式一 gitee.com/tanpf/tools | 方式二 gowks/dws | |-----|------|------| | 工程模式 | GOPATH 模式(无 go.mod) | Go Modules(go.mod 首行 module gowks) | | 路径含义 | 包目录相对 $GOPATH/src 的路径 | 模块名 + 包相对模块根的路径 | | 工程位置 | 必须钉在 $GOPATH/src 内 | 任意目录、任意盘符 | | 前缀要求 | 域名式命名空间防重名 | 模块名随意,无需域名 | | 依赖版本 | 全局一份,多版本无法共存 | 每模块独立,go.sum 锁定 | | 写法 | 长 | 短,语义清晰 |
### GOPATH 模式原理(gitee.com/tanpf/tools) Go 1.11 之前的唯一方式。核心规则只有一条:**import 路径 = 包目录相对 $GOPATH/src 的路径**,编译时 Go 拿着 import 字符串去 $GOPATH/src 下找同名目录。 fibu2 工程在本机的布局(GOPATH=/wks/gowks,软链到 /mnt/g/wks/gowks): ```text /wks/gowks/ # GOPATH 根 └── src/ # 所有源码必须在它下面 ├── cmd/fibu2/fibu2.go # package main ├── tools/ # 工具包真身(src/tools) ├── gin/dc/client/ # dcc 引入的包 └── vendor/ # 第三方依赖 ``` 要点: - **域名前缀只是目录名**:gitee.com/tanpf/tools 不是网址,编译不联网,它只要求包物理放在 $GOPATH/src/gitee.com/tanpf/tools;域名起命名空间作用,防止大家的 tools 包互相冲突 - **路径与磁盘强耦合**:import 写死了 src 下的目录位置,每台机器都要把包按相同路径摆好。本机 G 盘副本里只有 src/tools、没有 src/gitee.com/tanpf/tools,fibu2.go 在这份副本上就找不到包——GOPATH 模式的典型痛点 - **老工程需 GO111MODULE=off**:本机 go env GO111MODULE=on,编译 fibu2 这类无 go.mod 的工程要临时切回 GOPATH 模式 - 第三方依赖放 src/vendor/ 下按相同规则解析;go get 会把源码直接拉进 src,污染工作区
### Go Modules 模式原理(gowks/dws) Go 1.11 引入、1.16 起默认开启。核心规则:**import 路径 = go.mod 里声明的模块名 + 包相对模块根的路径**。 dws 工程的布局(模块根 = /mnt/d/wks/gowks/src,go.mod 所在目录): ```text /mnt/d/wks/gowks/src/ # 模块根(有 go.mod 的目录) ├── go.mod # 首行 module gowks + 依赖清单 ├── go.sum # 依赖版本与校验和 ├── dws/ # import "gowks/dws" 的真身 │ ├── dws.go │ └── driver_pgx.go ├── tools/tools.go # 对应 import "gowks/tools" └── cmd/edws/dws.go # package main ``` 解析过程(编译 cmd/edws 时): 1. Go 从源文件所在目录向上查找 go.mod,找到模块根,得知模块名为 gowks 2. import "gowks/dws" 的前缀与模块名匹配,判定为模块内部包 3. 去掉前缀 gowks,映射到模块根下的 dws 目录 要点: - **模块名不必是域名**:gowks 这种短名只在模块内部使用;只有要发布给别人 go get 的公共模块才用完整域名(如 github.com/user/repo) - **工程与 GOPATH 解耦**:工程可放任意盘符任意目录;第三方依赖不进 src,缓存在 GOMODCACHE(本机 /wks/gowks/pkg/mod) - **版本互不干扰**:每个模块独立维护依赖清单,多个工程依赖同一包的不同版本可以共存
### 使用方式与选型建议 Go Modules 工程(gowks/dws 这种)的日常操作,全部在模块根(go.mod 所在目录)执行: ```bash cd /mnt/d/wks/gowks/src go mod init gowks # 首次创建模块(已有 go.mod 则跳过) go mod tidy # 依据 import 整理依赖、更新 go.sum go build ./... # 编译模块内全部包 go build ./cmd/edws # 只编译 edws 这个命令 go run ./cmd/edws ping --host 127.0.0.1 # 直接运行 ``` GOPATH 工程(gitee.com/tanpf/tools 这种)在新版 Go 下的编译: ```bash export GO111MODULE=off # 新版 Go 默认 on,老工程需临时切回 cd /wks/gowks/src/cmd/fibu2 go build -o fibu2 fibu2.go ``` 老工程向 Modules 迁移(fibu2 这类工程的演进方向): ```bash cd /wks/gowks/src go mod init gowks # import 逐个改短:gitee.com/tanpf/tools 改为 gowks/tools(包已在模块内) ``` ```text # 包暂时留在原路径、不想改 import 时,可在 go.mod 里 replace 过渡: # replace gitee.com/tanpf/tools => ./tools ``` 选型结论: - 新工程一律 Go Modules:import 短、目录自由、依赖可锁版本 - gowks/dws 这种"模块名 + 包路径"是当前标准写法 - gitee.com/tanpf/tools 是 GOPATH 时代的历史写法,理解"src 下相对路径"的解析原理即可,便于维护 fibu2 等老工程
参考