gin_demo01 % tree
.
├── app
├── go.mod
├── go.sum
├── main.go
├── readme.md
└── web
├── DEPLOYMENT_README.md
├── _redirects
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── assets
│ ├── AssetManifest.bin
│ ├── AssetManifest.bin.json
│ ├── AssetManifest.json
│ ├── FontManifest.json
│ ├── NOTICES
│ ├── assets
│ │ ├── icons
│ │ │ ├── VideoWnd_SpeakerOff.png
│ │ │ ├── baocun.png
│ │ │ ├── bofang.png
│ │ │ ├── chaxun.png
│ │ │ ├── daochu.png
│ │ │ ├── fl-dingdan.png
│ │ │ ├── google.png
│ │ │ ├── home.png
│ │ │ ├── jilu.png
│ │ │ ├── kefu.png
│ │ │ ├── zhongxinhecheng.png
│ │ │ └── zu-.png
│ │ └── img
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon.ico
│ │ └── site.webmanifest
│ ├── fonts
│ │ └── MaterialIcons-Regular.otf
│ ├── packages
│ │ ├── cupertino_icons
│ │ │ └── assets
│ │ │ └── CupertinoIcons.ttf
│ │ ├── flutter_inappwebview
│ │ │ └── assets
│ │ │ └── t_rex_runner
│ │ │ ├── t-rex.css
│ │ │ └── t-rex.html
│ │ ├── flutter_inappwebview_web
│ │ │ └── assets
│ │ │ └── web
│ │ │ └── web_support.js
│ │ ├── iconsax_flutter
│ │ │ └── fonts
│ │ │ └── FlutterIconsax.ttf
│ │ ├── media_kit
│ │ │ └── assets
│ │ │ └── web
│ │ │ └── hls1.4.10.js
│ │ └── wakelock_plus
│ │ └── assets
│ │ └── no_sleep.js
│ └── shaders
│ └── ink_sparkle.frag
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon-96x96.png
├── favicon.ico
├── favicon.svg
├── flutter.js
├── flutter_bootstrap.js
├── flutter_service_worker.js
├── index.html
├── main.dart.js
├── manifest.json
├── nginx.conf.cdn
├── nginx.conf.example
├── site.webmanifest
├── version.json
├── web-app-manifest-192x192.png
└── web-app-manifest-512x512.png
25 directories, 96 files
(base) apple@apple15 gin_demo01 %
直接运行
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
gin.SetMode(gin.ReleaseMode) // 设置为发布模式,关闭调试日志
r := gin.Default()
// 静态文件服务
r.Static("/", "./web")
// 访问根路径时返回 index.html
r.NoRoute(func(c *gin.Context) {
if c.Request.URL.Path == "/" {
c.File("./web/index.html")
} else {
c.Status(http.StatusNotFound)
}
})
r.Run(":8040")
}
如果想把 Go 程序和 web 目录一起打包,做到“一键运行即访问”,有两种常见方式:
方式一:直接拷贝 web 目录
保证 web 目录和编译后的可执行文件在同一目录下。
用如下命令编译并运行:
go build -o app
./app
这样访问静态文件时,程序会自动读取同目录下的 web 文件夹。
方式二:将 web 目录打包进二进制(推荐用 embed)
Go 1.16+ 支持 embed,可以把静态资源直接打进可执行文件,无需单独拷贝 web 目录。
修改 main.go,引入 embed 并用 gin 的 StaticFS:
package main
import (
"embed"
"github.com/gin-gonic/gin"
"io/fs"
"net/http"
)
//go:embed web/*
var webFS embed.FS
func main() {
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
// 将 web 目录嵌入到二进制中
fSys, _ := fs.Sub(webFS, "web")
r.StaticFS("/", http.FS(fSys))
r.NoRoute(func(c *gin.Context) {
if c.Request.URL.Path == "/" {
c.FileFromFS("index.html", http.FS(fSys))
} else {
c.Status(http.StatusNotFound)
}
})
r.Run(":8040")
}
重新编译你的程序:
go build -o app
./app
这样,web 目录的所有内容都被打包进了二进制文件,无需再单独拷贝目录,部署更方便。