城南旧巷 烟花散作尘
石阶斑驳 犹刻旧年痕
孤城雨村 霜雪染心门
缘分浮沉 人事易离分
你有没有过这种崩溃时刻?
你改了 Go 后端的 UserResponse 结构体,加了个 avatar_url 字段。
前端 React 组件还在用 avatar,一跑就报 undefined。
你翻了三天的 Git 提交记录,才在一条被淹没的 PR 里找到更新说明。
你问同事:“后端改了字段,你那边更新了吗?”
他回:“哦,我忘了,马上改。”
💥 传统前后端开发,像两个孤岛,靠口头通知和过期文档勉强维持。
而 Cursor 推出的「多根工作区」功能,彻底打破了这种割裂。
它让你的 React 前端和 Go 后端,像同一个项目一样被 AI 理解、联动、重构、生成。
今天,我用一个真实项目,手把手教你:
✅ 用 .code-workspace 文件管理 React + Go 双项目
✅ Ctrl+点击,直接从前端跳到后端结构体
✅ AI 一键同步字段命名,跨语言自动映射
✅ 问 AI:“怎么调用 /api/users/{id}?”→ 自动生成 fetch 代码
✅ 让 AI 为你写完整登录流程:表单 → JWT → localStorage → 跳转
这不是“打开两个项目”,这是让 AI 成为你真正的全栈搭档。
第一部分:用 .code-workspace 管理你的双项目
Cursor 支持 VS Code 的 .code-workspace 配置文件——这才是团队协作的黄金标准。
把下面这段 JSON,保存为 .code-workspace文件,放在你的项目根目录下:
{
"folders": [
{
"name": "Frontend (React 18 + TS)",
"path": "frontend",
"settings": {
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.suggest.autoImports": true,
"editor.formatOnSave": true,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"files.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/build": true
}
}
},
{
"name": "Backend (Go 1.21 + Gin)",
"path": "backend",
"settings": {
"go.goroot": "/usr/local/go",
"go.useLanguageServer": true,
"editor.formatOnSave": true,
"files.exclude": {
"**/vendor": true
}
}
},
{
"name": "Shared Types",
"path": "shared"
},
{
"name": "API Docs",
"path": "docs"
}
],
"settings": {
"cursor.ai.enabled": true,
"cursor.ai.allowCodeUpload": false,
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/vendor": true
}
},
"extensions": {
"recommendations": [
"ms-vscode.vscode-typescript-next",
"golang.go",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint"
]
}
}
📌 关键说明:
-
把 .code-workspace 和 frontend、backend 文件夹放在同一级目录
-
提交到 Git,团队共享,AI 上下文一致
-
“allowCodeUpload”设为 false,保护企业代码安全
第二部分:Ctrl+点击,秒跳前后端
你在 frontend/src/types/user.ts 里看到:
export interface User {
id: number;
username: string;
avatar: string; // 👈 这个字段后端叫什么?
email: string;
}
以前你要:打开 backend → 找 models/user.go → 搜索 Avatar → 看到 AvatarURL → 记下来 → 回来改。
现在:
👉 直接在 avatar 上,【按住 Ctrl + 点击】
👉 一秒跳到 backend/models/user.go:
type UserResponse struct {
ID int `json:"id"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"` // ← 跳到这里!
Email string `json:"email"`
}
AI 不仅知道字段对应关系,还懂 JSON 映射:avatar ↔ avatar_url!
第三部分:AI 一键同步字段命名
你决定统一命名风格:
Go 用 snake_case,前端用 camelCase。
你发现:
-
Go 的 AvatarURL → 前端是 avatar ✅
-
Go 的 CreatedAt → 前端还是 CreatedAt ❌(没改!)
你不想手动改 10 个地方。
现在:
-
在 Go 文件里选中 AvatarURL
-
右键 → 【Ask Cursor:Rename this field to avatar and update all corresponding TypeScript interfaces】
AI 自动扫描:
✅ backend/models/user.go:AvatarURL → avatar
✅ frontend/src/types/user.ts:avatar(不变)
✅ frontend/src/types/order.ts:CreatedAt → createdAt
✅ frontend/src/api/userApi.ts:response.avatar_url → response.avatar
点击【Apply All】,一键完成,自动生成提交信息:
refactor: unify field naming: snake\_case → camelCase across frontend & backend (#456)
AI 懂得:json:"avatar_url" 对应前端的 avatar,不是 avatarUrl!
第四部分:问 AI 怎么调接口,它直接给你写代
你是前端新人,第一次调用户接口:
你问:
【怎么在 React 里调用 Go 的 /api/users/{id}?需要传 token 吗?怎么处理 401?】
AI 读取:
-
backend/main.go → 确认路由是 GET /api/users/{id}
-
backend/handlers/user.go → 确认返回 UserResponse
-
frontend/types/user.ts → 获取 User 类型
-
docs/api.yaml → 确认用 Bearer Token 认证
然后直接生成:
import axios from 'axios';
import { User } from '../types/user';
const API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8080';
export const getUserById = async (id: number): Promise<User> => {
const token = localStorage.getItem('authToken');
if (!token) {
window.location.href = '/login';
throw new Error('No auth token');
}
try {
const response = await axios.get<User>(`${API_BASE}/api/users/${id}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
return response.data;
} catch (error) {
if (axios.isAxiosError(error) && error.response?.status === 401) {
localStorage.removeItem('authToken');
window.location.href = '/login';
}
throw error;
}
};
✅ 自动引入 axios
✅ 自动匹配 User 类型
✅ 自动处理 401 跳转
✅ 自动读取环境变量 VITE_API_BASE
第五部分:AI 直接帮你写完整登录页
你想实现:
-
前端输入 username/password
-
调用 Go 的 /api/auth/login
-
接收 token 和 user 对象
-
存入 localStorage
-
跳转到 /dashboard
你以前要:写表单 → 写 fetch → 写状态管理 → 调试失败 → 改 → 再调试
现在:
在 Login.tsx 文件里,按 Ctrl + K,输入:
生成一个完整的登录流程:
React 组件,包含用户名/密码输入框
提交时调用 Go 后端的 POST /api/auth/login 接口
成功时,将令牌存储在 localStorage 中并重定向到 /dashboard
失败时,显示错误消息
使用共享类型中的 User 类型
假设 Go 后端返回 { token: string, user: User }
AI 读取:
-
backend/handlers/auth.go → 确认接口返回 { token, user }
-
frontend/types/user.ts → 确认 User 类型结构
然后直接生成完整可运行代码:
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { getUserById } from '../api/userApi';
import { User } from '../types/user';
export default function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
try {
const response = await fetch('http://localhost:8080/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (!response.ok) {
throw new Error('Login failed');
}
const data = await response.json();
localStorage.setItem('authToken', data.token);
localStorage.setItem('user', JSON.stringify(data.user));
await getUserById(data.user.id);
navigate('/dashboard');
} catch (err) {
setError('用户名或密码错误');
}
};
return (
<div style={{ padding: '40px' }}>
<h2>登录</h2>
{error && <p style={{ color: 'red' }}>{error}</p>}
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="用户名"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
<input
type="password"
placeholder="密码"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<button type="submit">登录</button>
</form>
</div>
);
}
你不需要懂 Go,不需要查文档,AI 为你打通了整个链路
结语
Cursor 不是“更好的 VS Code”。
它是第一个真正理解你整个技术栈(前端 + 后端 + API + 类型)的 AI 原生开发环境。
当你能在一个窗口里, 让 AI 理解你的 React 组件如何与 Go 接口通信、字段如何映射、错误如何处理, 此时你是一个指挥 AI 协同作战的全栈架构师。
打开你的 .code-workspace,让 Cursor 成为你真正的搭档。
