使用Golang、WASM和React实现REST API调用的示例
使用Golang、WASM和React实现REST API调用的示例 我对Golang非常陌生,正在尝试创建一个可以通过WASM共享并在React应用中使用的Golang REST API。我正在寻找能够提供一个示例来帮助我的人。
amitsingh0542:
我是 Go 语言的新手,正在尝试创建一个可以通过 WASM 共享并在 React 应用中使用的 Go REST API。我正在寻找能提供一个示例来帮助我的人。
要创建一个用于 React 应用(通过 WASM)的 Go REST API,你需要构建一个简单的 Go HTTP 服务器,使用 GOOS=js GOARCH=wasm go build 将其编译为 main.wasm,并通过一个基本的 HTML 文件配合 wasm_exec.js 来提供它。在 React 中,使用 axios 从 WASM API 的端点(示例中是 /message)获取数据。请记住处理好 CORS 和错误处理,并为生产环境正确提供 WASM 文件。
更多关于使用Golang、WASM和React实现REST API调用的示例的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
amitsingh0542: 创建一个可以通过WASM共享并在React应用中使用的Golang REST API。
据我所知,WASM减少了对与公共Web服务器交互的需求——仅仅是加载?这更像是一种旧的客户端-服务器解决方案。这意味着所有通信都直接从WASM客户端到一个完全开放的API?我认为,你可以通过某种令牌来限制从WASM(客户端)对API的访问。
我也对WASM感兴趣,但我的设想是API应该完全锁定,禁止从互联网访问。只能通过本地主机或内部IP访问。
所以我的理解是,WASM既是现代的Web应用,同时又是老式的桌面应用。为了使API尽可能“安全隔离”,我选择了一个传统的SPA/PWA Web应用,通过Web服务器从内部IP访问。
这不是对你问题的直接回答,而是为你构建API时如何思考提供一个基础?
以下是一个完整的示例,展示如何使用Go编译为WebAssembly,并在React应用中调用REST API:
1. Go WebAssembly 代码 (main.go)
package main
import (
"encoding/json"
"fmt"
"syscall/js"
"net/http"
"io/ioutil"
"bytes"
)
// APIResponse 定义API响应结构
type APIResponse struct {
Data interface{} `json:"data"`
Message string `json:"message"`
Success bool `json:"success"`
}
// User 示例数据结构
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
// 全局HTTP客户端
var client = &http.Client{}
func makeAPICall(this js.Value, args []js.Value) interface{} {
url := args[0].String()
method := args[1].String()
bodyData := args[2].String()
promise := js.Global().Get("Promise").New(js.FuncOf(func(this js.Value, promiseArgs []js.Value) interface{} {
resolve := promiseArgs[0]
reject := promiseArgs[1]
go func() {
var req *http.Request
var err error
if bodyData != "" {
req, err = http.NewRequest(method, url, bytes.NewBuffer([]byte(bodyData)))
if err != nil {
reject.Invoke(err.Error())
return
}
req.Header.Set("Content-Type", "application/json")
} else {
req, err = http.NewRequest(method, url, nil)
if err != nil {
reject.Invoke(err.Error())
return
}
}
resp, err := client.Do(req)
if err != nil {
reject.Invoke(err.Error())
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
reject.Invoke(err.Error())
return
}
// 创建JavaScript对象返回
result := js.Global().Get("Object").New()
result.Set("status", resp.StatusCode)
result.Set("body", string(body))
result.Set("headers", js.ValueOf(resp.Header))
resolve.Invoke(result)
}()
return nil
}))
return promise
}
func getUsers(this js.Value, args []js.Value) interface{} {
url := "https://jsonplaceholder.typicode.com/users"
promise := js.Global().Get("Promise").New(js.FuncOf(func(this js.Value, promiseArgs []js.Value) interface{} {
resolve := promiseArgs[0]
reject := promiseArgs[1]
go func() {
resp, err := http.Get(url)
if err != nil {
reject.Invoke(err.Error())
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
reject.Invoke(err.Error())
return
}
var users []User
err = json.Unmarshal(body, &users)
if err != nil {
reject.Invoke(err.Error())
return
}
// 转换为JavaScript数组
jsArray := js.Global().Get("Array").New(len(users))
for i, user := range users {
obj := js.Global().Get("Object").New()
obj.Set("id", user.ID)
obj.Set("name", user.Name)
obj.Set("email", user.Email)
jsArray.SetIndex(i, obj)
}
resolve.Invoke(jsArray)
}()
return nil
}))
return promise
}
func registerFunctions() {
js.Global().Set("goMakeAPICall", js.FuncOf(makeAPICall))
js.Global().Set("goGetUsers", js.FuncOf(getUsers))
}
func main() {
c := make(chan struct{}, 0)
registerFunctions()
<-c
}
2. 编译为WebAssembly
创建编译脚本 build.sh:
#!/bin/bash
GOOS=js GOARCH=wasm go build -o main.wasm main.go
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
3. React组件 (GoWasmComponent.jsx)
import React, { useEffect, useRef, useState } from 'react';
const GoWasmComponent = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
const [response, setResponse] = useState('');
const wasmLoaded = useRef(false);
useEffect(() => {
if (!wasmLoaded.current) {
loadWasm();
wasmLoaded.current = true;
}
}, []);
const loadWasm = async () => {
try {
const go = new window.Go();
const result = await WebAssembly.instantiateStreaming(
fetch('/main.wasm'),
go.importObject
);
go.run(result.instance);
console.log('Go WASM loaded successfully');
} catch (error) {
console.error('Failed to load WASM:', error);
}
};
const fetchUsers = async () => {
setLoading(true);
try {
if (window.goGetUsers) {
const users = await window.goGetUsers();
setUsers(users);
} else {
console.error('WASM function not available');
}
} catch (error) {
console.error('Error fetching users:', error);
} finally {
setLoading(false);
}
};
const callCustomAPI = async () => {
try {
if (window.goMakeAPICall) {
const apiUrl = 'https://jsonplaceholder.typicode.com/posts';
const method = 'POST';
const postData = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1
});
const result = await window.goMakeAPICall(apiUrl, method, postData);
setResponse(JSON.stringify({
status: result.status,
body: JSON.parse(result.body),
headers: result.headers
}, null, 2));
}
} catch (error) {
console.error('API call failed:', error);
setResponse(`Error: ${error.message}`);
}
};
return (
<div style={{ padding: '20px' }}>
<h2>Go WASM REST API Demo</h2>
<div style={{ marginBottom: '20px' }}>
<button
onClick={fetchUsers}
disabled={loading}
style={{
padding: '10px 20px',
marginRight: '10px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
{loading ? 'Loading...' : 'Fetch Users via WASM'}
</button>
<button
onClick={callCustomAPI}
style={{
padding: '10px 20px',
backgroundColor: '#28a745',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Test POST Request
</button>
</div>
{users.length > 0 && (
<div style={{ marginBottom: '20px' }}>
<h3>Users fetched via Go WASM:</h3>
<ul style={{ listStyle: 'none', padding: 0 }}>
{users.map(user => (
<li key={user.id} style={{
padding: '10px',
marginBottom: '5px',
backgroundColor: '#f8f9fa',
border: '1px solid #dee2e6',
borderRadius: '4px'
}}>
<strong>{user.name}</strong> - {user.email}
</li>
))}
</ul>
</div>
)}
{response && (
<div>
<h3>API Response:</h3>
<pre style={{
backgroundColor: '#f8f9fa',
padding: '15px',
border: '1px solid #dee2e6',
borderRadius: '4px',
overflow: 'auto'
}}>
{response}
</pre>
</div>
)}
</div>
);
};
export default GoWasmComponent;
4. 主应用入口 (App.js)
import React from 'react';
import GoWasmComponent from './GoWasmComponent';
function App() {
return (
<div className="App">
<GoWasmComponent />
</div>
);
}
export default App;
5. 项目结构
project/
├── go/
│ ├── main.go
│ └── build.sh
├── public/
│ ├── index.html
│ └── main.wasm
├── src/
│ ├── App.js
│ └── GoWasmComponent.jsx
├── package.json
└── wasm_exec.js
6. 运行步骤
- 编译Go为WASM:
cd go
chmod +x build.sh
./build.sh
-
将生成的
main.wasm和wasm_exec.js复制到React项目的public目录 -
在React应用中导入wasm_exec.js,在public/index.html中添加:
<script src="%PUBLIC_URL%/wasm_exec.js"></script>
- 启动React应用:
npm start
这个示例展示了如何通过Go WebAssembly在React应用中执行REST API调用,包括GET和POST请求。Go代码编译为WASM后,通过JavaScript Promise与React组件进行异步交互。

