参考 blog
环境搭建 需要安装 create-react-app
以及 go
, 在 Archlinux 上为:
1 2 sudo pacman -S go sudo npm install -g create-react-app
(这里是全局安装 create-react-app
)
创建项目以及启动一个 http 服务 1 2 3 npx create-react-app my-react-appcd my-react-app npm start
用 go 启用一个基础的 HTTP server 监听端口以及处理请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport ( "net/http" )func main () { http.HandleFunc("/" , func (w http.ResponseWriter, r *http.Request) { w.Write([]byte ("Hello from Golang server!" )) }) http.ListenAndServe(":8080" , nil ) }
Golang 中处理 HTTP 请求的方法 利用 net/http
库, 需要定义:
访问路径, 如 /api/data
处理函数, 如 dataHandler
监听接口, 如 :8080
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package mainimport ( "net/http" )func main () { http.HandleFunc("/api/data" , dataHandler) http.ListenAndServe(":8080" , nil ) }func dataHandler (w http.ResponseWriter, r *http.Request) { }
将 Golang 数据结构以 JSON 形式返回响应 1 2 3 4 5 6 7 8 9 type ApiResponse struct { Message string `json:"message"` }func dataHandler (w http.ResponseWriter, r *http.Request) { response := ApiResponse{Message: "Hello from the Golang API!" } json.NewEncoder(w).Encode(response) }
React 前端向 Golang 后端发起请求 用 fetch
API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import { useState, useEffect } from 'react' ;export default function Test ( ) { const [data, setData] = useState (null ); async function fetchData ( ) { try { const response = await fetch ('http://localhost:8080/' ); const data = await response.json (); setData (data) } catch (error) { console .error ('Error: ' , error); } } useEffect (() => { fetchData (); }, []); if (!data) { return <div > Loading...</div > } return ( <h1 > {data.message}</h1 > ); }
React 前端创建来自用户的请求 1 2 3 4 5 6 7 8 9 10 11 import Test from "./fetch/test" function App ( ) { return ( <div > <Test /> </div > ); }export default App ;
Go Server 处理静态文件 1 2 3 4 5 6 7 8 9 func main () { fs := http.FileServer(http.Dir("build" )) http.Handle("/" , fs) http.HandleFunc("/api/data" , dataHandler) http.ListenAndServe(":8080" , nil ) }
http.FileServer(http.Dir("build"))
创建了一个 HTTP 文件服务器, 它将服务于 build
目录中的静态文件
http.Handle("/", fs)
将这个文件服务器注册为根路径 /
的处理器
当客户端访问根路径 (例如 http://localhost:8080/
) 时, Go 服务器将自动从 build
目录中提供相应的静态文件
http.HandleFunc("/api/data", dataHandler)
注册了一个名为 dataHandler
的函数, 用于处理 /api/data
路径的请求
当客户端访问 /api/data
路径时, Go 服务器将调用 dataHandler
函数来处理该请求
另一种更好的组织方法:
1 2 3 4 5 6 7 8 9 10 11 12 func main () { fs := http.FileServer(http.Dir("build" )) http.Handle("/" , fs) api := http.NewServeMux() api.HandleFunc("/api/data" , dataHandler) http.Handle("/api/" , api) http.ListenAndServe(":8080" , nil ) }
http.ServeMux
是 Go 标准库中的一个 HTTP 请求多路复用器 (路由器), 可以处理 HTTP 请求的路由和分发
原本的对 /api/data
请求是注册到 /
路径下的, 在与 /
绑定的文件服务器 fs
下找静态资源, 而这样写后就将 /api/data
相关的请求都注册到 /api/
路径下, 在 api
这一 http.ServeMux
下找资源.
热加载开发环境 React 自然支持, 对于 Golang 可以使用类似 fresh
的工具:
1 2 go install github.com/pilu/fresh@latest fresh
Debug 技巧 对于 React 使用 console.log
.
对于 Golang 用 error
类型:
1 2 3 4 5 6 7 8 9 func dataHandler (w http.ResponseWriter, r *http.Request) { err := errors.New("an error occurred" ) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }
React 部分的测试 也可以考虑 Jest 或 React Testing 库:
1 2 3 4 5 6 7 8 import { render, screen } from '@testing-library/react' ;import App from './App' ;test ('renders learn react link' , () => { render (<App /> ); const linkElement = screen.getByText (/learn react/i ); expect (linkElement).toBeInTheDocument (); });
Golang 部分的测试 测试 API Endpoints, 用 net/http/httptest
库:
1 2 3 4 5 6 7 8 9 10 11 12 13 func TestApiHandler (t *testing.T) { req, err := http.NewRequest("GET" , "/api/data" , nil ) if err != nil { t.Fatal(err) } rr := httptest.NewRecorder() handler := http.HandlerFunc(dataHandler) handler.ServeHTTP(rr, req) }
构建二进制 对于 React:
对于 Golang: