面试题答案
一键面试- 使用上下文(Context):
- 原理:Go语言的
context
包提供了一种机制来传递截止时间、取消信号等,用于控制Goroutine的生命周期。 - 示例代码:
- 原理:Go语言的
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("Goroutine收到取消信号,停止工作")
return
default:
fmt.Println("Goroutine正在工作...")
time.Sleep(1 * time.Second)
}
}
}
在主函数中可以这样调用:
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
go worker(ctx)
time.Sleep(10 * time.Second)
}
- 说明:在
worker
函数中,通过select
监听ctx.Done()
通道。当ctx.Done()
通道接收到数据时,意味着上下文被取消,Goroutine可以安全地停止工作。在主函数中,使用context.WithTimeout
创建一个带有超时的上下文,defer cancel()
确保在函数结束时取消上下文,避免资源泄漏。
- 通道(Channel):
- 原理:通过向一个共享的通道发送特定信号,让Goroutine监听这个通道,接收到信号后停止工作。
- 示例代码:
package main
import (
"fmt"
"time"
)
func worker(stop chan struct{}) {
for {
select {
case <-stop:
fmt.Println("Goroutine收到停止信号,停止工作")
return
default:
fmt.Println("Goroutine正在工作...")
time.Sleep(1 * time.Second)
}
}
}
在主函数中调用:
func main() {
stop := make(chan struct{})
go worker(stop)
time.Sleep(5 * time.Second)
close(stop)
time.Sleep(1 * time.Second)
}
- 说明:
worker
函数监听stop
通道,当通道接收到数据(通过close(stop)
关闭通道来发送信号),Goroutine停止工作。主函数中在合适的时机关闭stop
通道,通知Goroutine停止。
- 资源管理:
- 文件句柄:
- 打开文件:使用
os.Open
或os.Create
等函数打开文件,返回*os.File
类型的文件句柄。 - 关闭文件:在Goroutine结束前,通过
defer file.Close()
确保文件句柄被关闭。例如:
- 打开文件:使用
- 文件句柄:
func fileWorker(ctx context.Context) {
file, err := os.Open("test.txt")
if err!= nil {
// 处理错误
}
defer file.Close()
for {
select {
case <-ctx.Done():
// 可以在这里进行一些文件相关的收尾工作
return
default:
// 文件操作
}
}
}
- 网络连接:
- 建立连接:如使用
net.Dial
等函数建立网络连接,返回net.Conn
类型的连接对象。 - 关闭连接:同样通过
defer conn.Close()
在Goroutine结束前关闭连接。例如:
- 建立连接:如使用
func networkWorker(ctx context.Context) {
conn, err := net.Dial("tcp", "127.0.0.1:8080")
if err!= nil {
// 处理错误
}
defer conn.Close()
for {
select {
case <-ctx.Done():
// 可以在这里进行一些网络连接相关的收尾工作
return
default:
// 网络数据读写操作
}
}
}
通过上述方法,可以在Goroutine不再需要时安全地停止它,并有效地管理和释放其占用的资源。