Vercel 部署 Go 应用完全指南
约 1636 字大约 5 分钟
2026-04-11
简介
Vercel 传统上以部署前端框架(Next.js、Vue、React)和 Node.js 后端而闻名,但现在它原生支持 Go 运行时(目前处于 Beta 阶段)。这意味着你可以在 Vercel 上部署完整的 Go HTTP 服务器或 Serverless 函数,与前端项目共享同一个仓库和部署流程。
本指南将详细介绍如何在 Vercel 上部署 Go 应用,包括 Serverless 函数和完整 HTTP 服务器两种模式。
核心概念
| 概念 | 说明 |
|---|---|
| Go Runtime | Vercel 内置的 Go 运行时,支持标准 net/http 和主流框架(gin、chi 等) |
| Serverless Functions | 放置在 /api 目录下的 .go 文件,每个文件自动成为独立的 Serverless 函数 |
| Full Server | 通过 main.go 入口部署完整的 HTTP 服务器 |
| Services | 允许在同一仓库中同时部署 Go 后端和前端应用(如 Next.js) |
前置要求
- 一个 Vercel 账户(所有计划均支持 Go 运行时)
- Git 仓库(GitHub、GitLab 或 Bitbucket)
- 本地 Go 开发环境(用于开发和测试)
go.mod和go.sum文件(用于依赖管理)
方式一:部署 Go Serverless 函数
这是最简单的方式,适合构建独立的 API 端点。
1. 项目结构
my-project/
├── api/
│ ├── index.go # /api/index 端点
│ └── users.go # /api/users 端点
├── go.mod
└── go.sum2. 创建 Serverless 函数
在 /api 目录下创建 .go 文件。每个文件必须导出一个符合 http.HandlerFunc 签名的函数:
package handler
import (
"encoding/json"
"net/http"
)
// Handler 导出函数,必须匹配 http.HandlerFunc 签名
func Handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"message": "Hello from Go Serverless Function!",
})
}关键要点:
- 函数名可以是任何有效的 Go 导出标识符(如
Handler、MyFunc) - 每个文件自动成为独立的 Vercel Function
- 所有文件共享根目录的
go.mod进行依赖解析
3. 配置 vercel.json
在项目根目录创建 vercel.json:
{
"builds": [
{
"src": "api/*.go",
"use": "@vercel/go"
}
],
"routes": [
{
"src": "/api/(.*)",
"dest": "/api/$1.go"
}
]
}方式二:部署完整 Go HTTP 服务器
适合需要运行完整后端应用(如 REST API、微服务)的场景。
1. 项目结构
my-go-server/
├── main.go # 服务器入口
├── go.mod
├── go.sum
└── vercel.json2. 创建 main.go 入口
Vercel 会自动检测以下入口点:
main.go(项目根目录)cmd/api/main.gocmd/server/main.go
package main
import (
"fmt"
"log"
"net/http"
"os"
"github.com/go-chi/chi/v5"
)
func main() {
r := chi.NewRouter()
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello from Go on Vercel!")
})
r.Get("/api/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"status":"ok"}`)
})
// 必须从环境变量读取端口
port := os.Getenv("PORT")
if port == "" {
port = "3000"
}
log.Printf("Server starting on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, r))
}3. 配置 vercel.json
{
"version": 2,
"builds": [
{
"src": "main.go",
"use": "@vercel/go"
}
]
}注意: 如果你的入口文件在其他位置,需要调整 src 路径。
配置选项详解
Go 版本
Vercel 从 go.mod 中读取 Go 版本。如果没有指定,默认使用最新支持的版本:
module myapp
go 1.21
require (
github.com/go-chi/chi/v5 v5.0.11
)自定义构建标志
在 vercel.json 中通过环境变量设置构建标志:
{
"build": {
"env": {
"GO_BUILD_FLAGS": "-ldflags '-s -w'"
}
}
}默认情况下,Vercel 会剥离调试符号以减小构建体积。
私有模块支持
如果你的项目依赖私有 Go 模块,需要添加 GIT_CREDENTIALS 环境变量:
- 在 Vercel 项目设置中添加环境变量
GIT_CREDENTIALS - 值为经过认证的 Git URL,例如:
https://username:token@github.com/owner/private-repo
支持 GitHub、GitLab、Bitbucket 和自建服务器。
部署步骤
方法 1:通过 Git 仓库部署(推荐)
- 将代码推送到 GitHub/GitLab/Bitbucket 仓库
- 登录 Vercel Dashboard
- 点击 Add New... → Project
- 导入你的 Git 仓库
- Vercel 会自动检测 Go 项目(识别
go.mod和入口文件) - 点击 Deploy
方法 2:通过 Vercel CLI 部署
# 安装 Vercel CLI
npm i -g vercel
# 登录 Vercel
vercel login
# 部署项目
vercel
# 生产环境部署
vercel --prod使用 Gin 框架示例
Vercel 支持主流 Go 框架。以下是使用 Gin 的完整示例:
package main
import (
"log"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello from Gin on Vercel!")
})
r.GET("/api/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{
"user_id": id,
"status": "active",
})
})
port := os.Getenv("PORT")
if port == "" {
port = "3000"
}
log.Fatal(r.Run(":" + port))
}最佳实践
始终提交
go.sum
确保构建的可重现性和依赖的确定性。从环境变量读取端口
必须使用os.Getenv("PORT")而非硬编码端口,否则部署会失败。优化构建体积
使用-ldflags '-s -w'剥离调试信息,减小二进制文件大小。利用 Serverless 函数隔离
如果只需几个 API 端点,使用/api目录比部署完整服务器更简单、成本更低。混合部署使用 Services
如果要在同一仓库中同时部署 Next.js 前端和 Go 后端,使用 Vercel Services 功能隔离部署。冷启动优化
Serverless 函数在冷启动时会有一定延迟,对延迟敏感的场景建议使用完整服务器模式。
局限性与注意事项
| 限制 | 说明 |
|---|---|
| Beta 状态 | Go 运行时目前处于 Beta 阶段,功能和稳定性可能变化 |
| 冷启动延迟 | Serverless 函数在空闲后首次调用会有数百毫秒的冷启动延迟 |
| 执行时间限制 | Serverless 函数有最大执行时间限制(Hobby 计划 10 秒,Pro 计划 15 秒) |
| 内存限制 | 函数可用内存有限,不适合内存密集型任务 |
| WebSocket 不支持 | Vercel Serverless 函数不支持 WebSocket 长连接 |
| 文件系统只读 | 部署后文件系统为只读,无法在运行时写入文件 |
多应用部署(前端 + Go 后端)
如果你想在同一仓库中同时部署 Next.js 前端和 Go 后端,可以使用 Vercel Services:
my-monorepo/
├── apps/
│ ├── web/ # Next.js 前端
│ │ ├── package.json
│ │ └── ...
│ └── api/ # Go 后端
│ ├── main.go
│ └── go.mod
└── vercel.json在 Vercel Dashboard 中为每个 Service 配置不同的根目录:
webService 根目录:apps/webapiService 根目录:apps/api
常见问题
Q: 为什么我的 Go 函数没有被调用?
确保函数签名正确:必须导出函数(首字母大写),且签名匹配 func(w http.ResponseWriter, r *http.Request)。
Q: 如何调试本地环境?
在本地直接运行:
go run main.go然后访问 http://localhost:3000。
Q: 支持哪些 Go 版本?
Vercel 支持主流的 Go 版本(通常 1.18+)。版本从 go.mod 中读取。
Q: 如何加速首次部署?
首次使用某个 Go 版本时,Vercel 需要下载工具链,会稍慢。后续部署会缓存该版本,速度会显著提升。
