diff --git a/planet/planet.go b/planet/planet.go index 03a9e6f..bda41af 100644 --- a/planet/planet.go +++ b/planet/planet.go @@ -25,7 +25,7 @@ func WherePlanetN(xt, zn int, jd float64, n int) float64 { t := (jd - 2451545) / 36525.0000 t /= 10 // 转为儒略千年数 - body := planetViews[xt] + body := planetViews()[xt] coord := body.coords[zn] baseOrderTerms := len(coord.orders[0]) diff --git a/planet/planet_test.go b/planet/planet_test.go index 1f846dc..b169e80 100644 --- a/planet/planet_test.go +++ b/planet/planet_test.go @@ -25,8 +25,9 @@ func TestWherePlanetNFullMatchesDefault(t *testing.T) { } func TestPlanetViewsMatchRawCuts(t *testing.T) { + views := planetViews() for bodyIndex, raw := range planetRawData { - view := planetViews[bodyIndex] + view := views[bodyIndex] if math.Float64bits(view.scale) != math.Float64bits(raw[0]) { t.Fatalf("body=%d scale mismatch", bodyIndex) } @@ -42,3 +43,15 @@ func TestPlanetViewsMatchRawCuts(t *testing.T) { } } } + +func TestBuildPlanetViewsRejectsInvalidCuts(t *testing.T) { + _, err := buildPlanetViews([][]float64{{ + 10000000000, + 20, 21, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, + }}) + if err == nil { + t.Fatal("expected invalid cut error") + } +} diff --git a/planet/view.go b/planet/view.go index df807f0..2f9ecda 100644 --- a/planet/view.go +++ b/planet/view.go @@ -1,6 +1,9 @@ package planet -import "fmt" +import ( + "fmt" + "sync" +) type coordSeriesView struct { orders [6][]float64 @@ -11,13 +14,27 @@ type planetView struct { coords [3]coordSeriesView } -var planetViews = buildPlanetViews(planetRawData) +var ( + planetViewsOnce sync.Once + planetViewsCache []planetView + planetViewsErr error +) -func buildPlanetViews(rawData [][]float64) []planetView { +func planetViews() []planetView { + planetViewsOnce.Do(func() { + planetViewsCache, planetViewsErr = buildPlanetViews(planetRawData) + }) + if planetViewsErr != nil { + panic(planetViewsErr) + } + return planetViewsCache +} + +func buildPlanetViews(rawData [][]float64) ([]planetView, error) { views := make([]planetView, len(rawData)) for bodyIndex, raw := range rawData { if len(raw) < 20 { - panic(fmt.Sprintf("planet raw data %d too short: %d", bodyIndex, len(raw))) + return nil, fmt.Errorf("planet raw data %d too short: %d", bodyIndex, len(raw)) } view := planetView{scale: raw[0]} for zn := 0; zn < 3; zn++ { @@ -26,12 +43,12 @@ func buildPlanetViews(rawData [][]float64) []planetView { start := int(raw[pn+order]) end := int(raw[pn+order+1]) if start < 0 || end < start || end > len(raw) { - panic(fmt.Sprintf("planet raw data %d coord %d order %d invalid cut: %d..%d (len=%d)", bodyIndex, zn, order, start, end, len(raw))) + return nil, fmt.Errorf("planet raw data %d coord %d order %d invalid cut: %d..%d (len=%d)", bodyIndex, zn, order, start, end, len(raw)) } view.coords[zn].orders[order] = raw[start:end] } } views[bodyIndex] = view } - return views + return views, nil }