Files
gobridge/example/worker.py
what b390effd8e feat: 添加 Python→Go 全双工回调支持(call_go)
- 新增 WithHandlers 选项,通过反射将 Go 结构体方法暴露给 Python
- 新增 callback/callback_result 消息类型,支持 Python 在处理中回调 Go
- client 侧新增 readResult,内联处理 callback,复用同一连接避免死锁
- Python 侧新增 call_go[T]() 泛型调用,支持 dataclass 自动构造
- 注入 GOBRIDGE_WORKER_ID/WORKER_COUNT 环境变量,支持多 worker 初始化分工
- 新增示例演示 Go→Python→Go→Python 四层全双工链路
- Python 包版本升至 0.1.1
2026-04-14 13:06:50 +08:00

141 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "python"))
import dataclasses
import threading
from typing import Iterator
from gobridge import expose, call_go, run, worker_id, worker_count
# ── worker_id / worker_count ──────────────────────────────────────────────────
# 只有 worker 0 才执行一次性初始化(如监听端口、建立长连接等),
# 其余 worker 跳过,避免端口冲突 / 重复连接。
print(f"[worker {worker_id}/{worker_count}] started", flush=True)
if worker_id == 0:
def _init_shared_resource():
# 示例:此处可启动 WebSocket 客户端、监听 TCP 端口等
print(f"[worker {worker_id}] shared resource initialized", flush=True)
threading.Thread(target=_init_shared_resource, daemon=True).start()
# ── 基础类型 ─────────────────────────────────────────────────────────────────
@expose
def add(a: int, b: int) -> int:
return a + b
@expose
def range_gen(start: int, stop: int) -> Iterator[int]:
"""流式输出:对应 Go 侧 Invoke[chan int]"""
for i in range(start, stop):
yield i
@expose
def sum_stream(numbers: Iterator[int]) -> int:
"""流式输入:对应 Go 侧传入 chan int 参数"""
return sum(numbers)
@expose
def double_stream(numbers: Iterator[int]) -> Iterator[int]:
"""双向流输入每个数yield 其平方"""
for n in numbers:
yield n * n
# ── structdataclass / dict类型 ───────────────────────────────────────────
@dataclasses.dataclass
class User:
id: int
name: str
score: float
level: str = ""
@expose
def get_user(uid: int) -> dict:
"""普通调用:返回一个 structGo 对应 User"""
return {"id": uid, "name": f"user_{uid}", "score": uid * 1.5}
@expose
def total_score(users: list) -> float:
"""slice 输入:接收 []User返回总分"""
return sum(u["score"] for u in users)
@expose
def enrich_users(users: list) -> list:
"""slice 输入输出:为每个 user 追加 level 字段"""
result = []
for u in users:
u = dict(u)
u["level"] = "gold" if u["score"] >= 10 else "silver"
result.append(u)
return result
@expose
def gen_users(count: int) -> Iterator[dict]:
"""流式输出 structyield 多个 User对应 Go 侧 Invoke[chan User]"""
for i in range(1, count + 1):
yield {"id": i, "name": f"user_{i}", "score": float(i * 3)}
@expose
def process_users(users: Iterator[dict]) -> Iterator[dict]:
"""双向流 struct输入流式 Useryield 处理后的 User"""
for u in users:
yield {"id": u["id"], "name": u["name"].upper(), "score": u["score"] * 2}
# ── Server 全双工示例 ────────────────────────────────────────────────────────
@expose
def compute_with_go_mul(a: int, b: int) -> int:
"""示例1call_go[int] 指定返回类型"""
return call_go[int]("Multiply", a, b)
@expose
def squared_with_log(n: int) -> Iterator[int]:
"""示例2流式输出每次 yield 前 call_go("Log") 回调 Go"""
for i in range(1, n + 1):
call_go("Log", f"yielding {i}² = {i * i}")
yield i * i
@expose
def to_upper(s: str) -> str:
"""辅助方法:被 Go 的 EnrichName handler 内部调用"""
return s.upper()
@expose
def full_chain(name: str) -> str:
"""示例3Go→Python→Go→Python 四层链路
full_chain("world")
→ call_go[str]("EnrichName", "world") # Python 调 Go
→ Invoke[string](ctx, serv, "to_upper", "world") # Go 再调 Python
"WORLD"
"Hello, WORLD!"
"Hello, WORLD!"
"""
return call_go[str]("EnrichName", name)
@expose
def get_user_via_go(uid: int) -> dict:
"""示例4call_go[User] 自动将 Go 返回的 dict 构造为 dataclass 实例"""
user = call_go[User]("MakeUser", uid) # Go 返回 {"id":..,"name":..,"score":..}
user.level = "gold" if user.score >= 10 else "silver"
return dataclasses.asdict(user)
run()