面试题答案
一键面试- 定义 Context:
- 使用
context.Context
类型,它是Go语言中用于传递截止时间、取消信号和其他请求范围值的对象。可以通过context.Background()
创建一个根Context
,它通常作为所有请求Context
的起点。 - 例如:
ctx := context.Background()
- 使用
- 任务取消:
- 为了能够取消任务,使用
context.WithCancel(parent)
函数创建一个可取消的Context
。该函数返回一个新的Context
和一个取消函数CancelFunc
。当调用CancelFunc
时,会取消新的Context
,所有基于这个Context
创建的子Context
也会被取消。 - 示例代码:
parent := context.Background() ctx, cancel := context.WithCancel(parent) defer cancel() // 确保任务结束时调用取消函数,释放资源
- 为了能够取消任务,使用
- 设置截止时间:
- 对于可能长时间运行的任务,可以使用
context.WithDeadline(parent, deadline)
或context.WithTimeout(parent, timeout)
来设置任务的截止时间。这会在到达截止时间时自动取消任务。 - 例如:
parent := context.Background() deadline := time.Now().Add(5 * time.Second) ctx, cancel := context.WithDeadline(parent, deadline) defer cancel()
- 对于可能长时间运行的任务,可以使用
- 子任务的 Context 传递:
- 在启动子任务时,将父任务的
Context
传递给子任务。这样当父任务取消或到达截止时间时,子任务也能收到相应的取消信号。 - 例如,假设存在一个函数
runSubTask
来启动子任务:
func runSubTask(ctx context.Context) { // 子任务逻辑 } func main() { ctx := context.Background() go runSubTask(ctx) }
- 在启动子任务时,将父任务的
- 资源管理:
- 文件句柄:在打开文件时,使用
Context
来监控任务的取消状态。如果在读取或写入文件过程中任务被取消,要及时关闭文件句柄。
func readFile(ctx context.Context, filePath string) ([]byte, error) { file, err := os.Open(filePath) if err!= nil { return nil, err } defer file.Close() var result []byte buf := make([]byte, 1024) for { select { case <-ctx.Done(): return nil, ctx.Err() default: n, err := file.Read(buf) if err!= nil && err!= io.EOF { return nil, err } if n == 0 { break } result = append(result, buf[:n]...) } } return result, nil }
- 网络连接:类似地,在建立网络连接时,使用
Context
管理连接的生命周期。如果任务取消,关闭网络连接。
func connect(ctx context.Context, addr string) (net.Conn, error) { dialer := &net.Dialer{} conn, err := dialer.DialContext(ctx, "tcp", addr) if err!= nil { return nil, err } return conn, nil }
- 文件句柄:在打开文件时,使用
- 一致性保证:
- 通过确保所有任务和子任务都基于同一个
Context
树进行操作来保证资源管理的一致性。所有基于该Context
的操作在取消或完成时,遵循相同的资源释放逻辑。 - 在整个任务处理系统中,将
Context
作为参数在不同函数和子任务间传递,确保每个涉及资源操作的地方都能感知到任务的取消或完成状态。
- 通过确保所有任务和子任务都基于同一个
通过以上步骤,可以通过 context
精确把控资源在任务取消或完成时的释放时机,同时保证子任务之间 context
传递和资源管理的一致性。