面试题答案
一键面试- 定义任务和结果类型:
- 首先定义每个任务返回的结果类型。例如:
type UserInfo struct { Name string Age int } type UserPermissions []string
- 定义任务函数:
- 为每个任务定义一个函数,这些函数返回相应的结果和可能的错误。例如:
func getUserInfo() (UserInfo, error) { // 模拟获取用户信息,这里可能是从数据库查询等操作 return UserInfo{Name: "John", Age: 30}, nil } func getUserPermissions() (UserPermissions, error) { // 模拟获取用户权限列表,可能是从权限系统查询 return UserPermissions{"read", "write"}, nil }
- 使用goroutine和channel收集结果:
- 创建用于接收结果和错误的channel。
infoCh := make(chan UserInfo, 1) permCh := make(chan UserPermissions, 1) errCh := make(chan error, 2)
- 使用goroutine异步执行任务,并将结果发送到相应的channel。
go func() { info, err := getUserInfo() if err!= nil { errCh <- err } else { infoCh <- info } close(infoCh) }() go func() { perm, err := getUserPermissions() if err!= nil { errCh <- err } else { permCh <- perm } close(permCh) }()
- 处理结果和错误:
- 使用
select
语句等待所有任务完成,并处理结果和错误。
var userInfo UserInfo var userPermissions UserPermissions var errors []error for i := 0; i < 2; i++ { select { case info := <-infoCh: userInfo = info case perm := <-permCh: userPermissions = perm case err := <-errCh: errors = append(errors, err) } } close(errCh) if len(errors) > 0 { // 处理错误,例如记录日志或返回错误给调用者 for _, err := range errors { log.Println("Error:", err) } return } // 处理收集到的结果 fmt.Printf("User Info: %+v\n", userInfo) fmt.Printf("User Permissions: %+v\n", userPermissions)
- 使用
总结来说,通过goroutine实现任务的异步执行,通过channel来传递结果和错误,再利用select
语句优雅地收集并处理这些结果和错误。这样可以充分利用Go语言的并发特性,高效地处理多个异步任务。