}
func CoursewareList() ([]Courseware, error) {
time.Sleep(3 * time.Second)
return []Courseware{
{Id: 1, Name: "课件1", Code: "CW1", CreateId: 1, CreateName: "", CoverId: 1, CoverPath: ""},
{Id: 2, Name: "课件2", Code: "CW2", CreateId: 2, CreateName: "", CoverId: 2, CoverPath: ""},
}, nil
}
当然,errgroup中也有针对上下文的errgroup.WithContext函数,如果我们想控制请求接口的时间,用这个是最合适不过的。如果请求超时会返回一个关闭上下文的报错,像下面这样
package main
import (
"context"
"fmt"
"golang.org/x/sync/errgroup"
"time"
)
type Courseware struct {
Id int64
Name string
Code string
CreateId int64
CreateName string
CoverId int64
CoverPath string
}
type User struct {
Id int64
Name string
}
type File struct {
Id int64
Path string
}
var coursewares []Courseware
var users map[int64]User
var files map[int64]File
var err error
func main() {
// 查询课件
...
// 获取用户ID、文件ID
...
// 定义一个带超时时间的上下文,1秒钟超时
ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second)
defer cancelFunc()
// 定义一个带上下文的errgroup,使用上面带有超时时间的上下文
eg, ctx := errgroup.WithContext(ctx)
// 此处放到协程里
eg.Go(func() error {
// 批量获取用户信息
users, err = UserMap(ctx, userIds)
if err != nil {
fmt.Println("获取用户错误:", err)
return err
}
return nil
})
// 此处放到协程里
eg.Go(func() error {
// 批量获取文件信息
files, err = FileMap(ctx, fileIds)
if err != nil {
fmt.Println("获取文件错误:", err)
return err
}
return nil
})
if goErr := eg.Wait(); goErr != nil {
fmt.Println("goroutine err:", err)
return
}
// 填充
for i, courseware := range coursewares {
if user, ok := users[courseware.CreateId]; ok {
coursewares[i].CreateName = user.Name
}
if file, ok := files[courseware.CoverId]; ok {
coursewares[i].CoverPath = file.Path
}
}
fmt.Println(coursewares)
}
func UserMap(ctx context.Context, ids []int64) (map[int64]User, error) {
result := make(chan map[int64]User)
go func() {
time.Sleep(2 * time.Second) // 假装请求超过1秒钟
result <- map[int64]User{
1: {Id: 1, Name: "liu"},
2: {Id: 2, Name: "kang"},
}
}()
select {
case <-ctx.Done(): // 如果上下文结束直接返回错误信息
return nil, ctx.Err()
case res := <-result: // 返回正确结果
return res, nil
}
}
func FileMap(ctx context.Context, ids []int64) (map[int64]File, error) {
return map[int64]File{
1: {Id: 1, Path: "/a/b/c.jpg"},
2: {Id: 2, Path: "/a/b/c/d.jpg"},
}, nil
}
func CoursewareList() ([]Courseware, error) {
time.Sleep(3 * time.Second)
return []Courseware{
{Id: 1, Name: "课件1", Code: "CW1", CreateId: 1, CreateName: "", CoverId: 1, CoverPath: ""},
{Id: 2, Name: "课件2", Code: "CW2", CreateId: 2, CreateName: "", CoverId: 2, CoverPath: ""},
}, nil
}
执行上面的代码:
go run waitgroup.go
获取用户错误: context deadline exceeded
goroutine err: context deadline exceeded