PPysolate SpineREAD THE CODE · UNDERSTAND THE SYSTEM
课程与章节
源码索引 / CURRENT IMPLEMENTATION

learning/go-patterns/stages/06-bounded/quote.go

53 行 · 点击行号可定位;函数链接随声明位置更新,不手填行号。

跳到函数 / 声明
package main

import (
	"context"
	"errors"
	"fmt"
)

var ErrUnknownItem = errors.New("unknown item")

type Price struct {
	Item  string
	Cents int
}
type PriceSource interface {
	Lookup(context.Context, string) (Price, error)
}
type Catalog map[string]int

func (c Catalog) Lookup(ctx context.Context, item string) (Price, error) {
	if err := ctx.Err(); err != nil {
		return Price{}, err
	}
	cents, ok := c[item]
	if !ok {
		return Price{}, fmt.Errorf("%w: %q", ErrUnknownItem, item)
	}
	return Price{Item: item, Cents: cents}, nil
}

type Service struct{ source PriceSource }

func NewService(source PriceSource) Service { return Service{source: source} }
func (s Service) Quote(ctx context.Context, item string) (Price, error) {
	price, err := s.source.Lookup(ctx, item)
	if err != nil {
		return Price{}, err
	}
	shipping, err := s.source.Lookup(ctx, "shipping")
	if err != nil {
		return Price{}, err
	}
	return Price{Item: item, Cents: price.Cents + shipping.Cents}, nil
}
func (s Service) QuoteMany(ctx context.Context, items []string, limit int) ([]Price, error) {
	quotes := make([]Price, len(items))
	tasks := make([]Task, len(items))
	for i, item := range items {
		tasks[i] = func() (string, error) { quote, err := s.Quote(ctx, item); quotes[i] = quote; return "", err }
	}
	_, err := RunBounded(tasks, limit)
	return quotes, err
}