概览
包结构、类型体系与阅读本参考的方式。
Go 包内嵌一份 WebAssembly 编译的核心,经纯 Go 的 wazero 运行时调用—— 不需要 cgo,交叉编译与静态链接都不受影响。
这一栏是 Go 侧的完整 API 参考——每个导出函数、类型与方法都有独立条目。
安装
go get github.com/x-haose/x-iztro/go/iztroimport "github.com/x-haose/x-iztro/go/iztro"第一张盘
chart, err := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageZhCN, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(chart.SolarDate, chart.LunarDate)
// 2000-8-16 二〇〇〇年七月十七
soul := chart.Palace(iztro.PalaceSoul)
if len(soul.MajorStars) > 0 {
fmt.Println(soul.MajorStars[0].Name)
// 紫微
} else {
fmt.Println("命宫是空宫,借对宫看:", soul.OppositePalace().MajorStars[0].Name)
}主星列表可能为空
一张盘上通常有两宫无主星(空宫),命宫也可能是其中之一。
直接写 soul.MajorStars[0] 在那种盘上会 panic——先判长度,或用
IsEmpty 分支到借对宫的写法。
包结构
包是扁平的,全部导出项都在 iztro 下。按主题划分:
| 主题 | 主要导出 | 本参考对应页 |
|---|---|---|
| 排盘 | BySolar、ByLunar、Rearranged | 排盘入口 |
| 数据类型 | Astrolabe、Palace、Star、Horoscope、Config | 星盘对象 起的四页 |
| 标识常量 | PalaceSoul、StarZiweiMaj、MutagenLu 等 | 数据表 |
| 轻量查询 | GetZodiacBySolarDate 等 | 轻量查询 |
| 工具函数 | FixIndex、GetBrightness 等 | 工具函数 |
| 安星 | GetMajorStar、GetHoroscopeStar 等 | 安星模块 |
| 数据表 | StarsInfo、HeavenlyStems 等 | 数据表 |
| 翻译 | Translate、KeyOf、KeyOfIn | 翻译 |
| 错误 | *Error、Err* 哨兵、Code* 常量 | 错误处理 |
| 运行时 | Warmup、Close、CompilationCacheDir | 本页下方 |
常量即标识
包里的标识常量取值就是语言无关标识,可直接与数据对象的 *Key 字段比较:
soul := chart.Palace(iztro.PalaceSoul)
fmt.Println(soul.MajorStars[0].Key == iztro.StarZiweiMaj)
// true它们都是无类型字符串常量,字符串字面量同样有效——
chart.Palace("soulPalace") 与 chart.Palace(iztro.PalaceSoul) 等价。
常量的价值在于 IDE 补全与拼写检查。
判断用 Key,不要用 Name
star.Name 随排盘语言变化(中文盘是「紫微」,英文盘是 emperor);
star.Key 在任何语言下都是 ziweiMaj。所有判断都应基于 *Key 字段或内置判断方法。
可变参数
需要传星耀列表或四化列表的方法一律用可变参数,调用处不必构造切片:
soul := chart.Palace(iztro.PalaceSoul)
target := chart.Palace(iztro.PalaceWealth)
fmt.Println(soul.Has(iztro.StarZiweiMaj, iztro.StarTianxiangMaj))
fmt.Println(soul.FliesTo(target, iztro.MutagenLu, iztro.MutagenJi))输出
false
false已有切片时用 ... 展开:
soul := chart.Palace(iztro.PalaceSoul)
stars := []string{iztro.StarZiweiMaj, iztro.StarTianxiangMaj}
fmt.Println(soul.Has(stars...))输出
false运限的流耀查询是例外
HasHoroscopeStars 一族的星耀参数是 []string 而非可变参数,
因为它前面已有宫名与层级两个字符串参数,可变参数会让调用处产生歧义。
错误处理
需要计算的入口都返回 (值, error);纯查询方法(Palace、Star、Has 等)不返回错误,
查不到时返回 nil 或零值。
_, err := iztro.BySolar("2000-13-1", 2, iztro.GenderFemale, true, iztro.LanguageZhCN, nil)
fmt.Println(err)
fmt.Println(errors.Is(err, iztro.ErrInvalidDate))
var e *iztro.Error
if errors.As(err, &e) {
fmt.Println(e.Code)
}输出
iztro: invalid solar date '2000-13-1': month must be within 1-12
true
invalid_date错误一律是 *iztro.Error,带机器可读的 Code,并可用 errors.Is 对四个哨兵匹配。
详见错误处理。
运行时与性能
wasm 模块编译一次、实例按需铺开:实例各持有自己的线性内存,
因此并发调用各占一个实例而不是共享一个加锁,实例数上限为 GOMAXPROCS。
排盘的热路径上没有全局互斥锁——取实例走 channel,只有运行时首次初始化与 Close
才加锁。多 goroutine 同时排盘因此能真正并行:同一台十核机器上,
8 个 goroutine 跑 800 次排盘比单 goroutine 快四倍出头。
编译产物落盘缓存在用户缓存目录下(CompilationCacheDir 可查),
按 wasm 内容哈希分桶,换了 wasm 自然换桶。
实测量级(Apple M 系列,10 核;具体数字随机器与 wasm 体积浮动):
| 阶段 | 耗时 |
|---|---|
| 首次调用,编译缓存未命中(要现编译 wasm) | 一两百毫秒 |
| 首次调用,编译缓存命中 | 二三十毫秒 |
| 稳态单次排盘 | 半毫秒上下 |
主要成本是 JSON 编解码不是计算
稳态那半毫秒里,大头是 wasm 侧把整张盘序列化成 JSON、Go 侧再反序列化成结构体,
而不是斗数推算本身。只需要个别字段时,用
轻量查询(GetMajorStarBySolarDate 一类)比排整盘划算得多。
Warmup / Close / CompilationCacheDir
func Warmup(ctx context.Context) error
func Close(ctx context.Context) error
func CompilationCacheDir(ctx context.Context) (string, error)| 函数 | 说明 |
|---|---|
Warmup | 预先完成编译并把实例池铺满,把冷启动开销提前到启动阶段。不调用也能正常工作——编译与实例化本来就是惰性的 |
Close | 关闭运行时、归还全部实例内存。通常不必调用;关闭后再调用本包任何函数会自动重新初始化 |
CompilationCacheDir | 返回编译缓存目录;未启用落盘缓存时返回空串 |
ctx := context.Background()
if err := iztro.Warmup(ctx); err != nil {
log.Fatal(err)
}
dir, err := iztro.CompilationCacheDir(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(dir != "")
chart, err := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageZhCN, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(chart.SolarDate)输出
true
2000-8-16服务进程希望第一个请求就走热路径时,在启动阶段调一次 Warmup 即可。
Context 变体
排盘、运限、重排、Prompt 这些要进 wasm 的入口都有一个 *Context 版本,
多收一个 context.Context:
| 无 ctx | 带 ctx |
|---|---|
BySolar / ByLunar | BySolarContext / ByLunarContext |
Astrolabe.Horoscope / HoroscopeNow | HoroscopeContext / HoroscopeNowContext |
Astrolabe.Rearranged | RearrangedContext |
Astrolabe.AstrolabeToPrompt / HoroscopeToPrompt | AstrolabeToPromptContext / HoroscopeToPromptContext |
| — | Warmup / Close / CompilationCacheDir 只有 ctx 版本 |
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
chart, err := iztro.BySolarContext(ctx, "2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageZhCN, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(chart.SolarDate)输出
2000-8-16ctx 管的是排队,不是计算
ctx 用于取消等待空闲 wasm 实例的排队。实例一旦拿到,wasm 侧的计算不可中断——
单次排盘本来就是亚毫秒级,没有需要中途打断的长任务。
wazero 编译器只覆盖 amd64 与 arm64
这两个架构上 wazero 走优化编译器(编译成机器码)。其余架构回落到解释器, 仍然能跑出正确结果,但速度会低一个量级以上。生产环境请部署在 amd64 或 arm64 上。
条目怎么读
每个 API 条目按固定八段组织:
示例统一用同一张盘:2000 年 8 月 16 日寅时女命, 方便跨页对照。这张盘的完整数据见数据结构。