go语言里如何强制关闭一个线程呢?

使用os包的FindProcess、Getpid等函数可以实现强制关闭进程。

但是线程的话我只能做到丢弃该线程,它还是在执行的,而且线程是直接挂在进程上,没啥父线程的概念。

所以我就来问问如何关闭一个线程呢?

话又说回来,go没有线程的概念啊,go routine貌似会根据需要实现为线程或者进程,那么我们应该如何强制关闭一个go程呢?

比如说我有个read操作,希望它在指定时间内完成,否则应该直接失败返回,返回的同时read应该被终结而不是在后台默默的偷窃数据。

read是封装好的,我们不能对其做操作,只能通过包装,应该怎么搞?

共 7 个回复


defia

需要判断超时的地方用select..

# 0

snake117

@defia 用select并不能让read函数关闭,它只是丢弃了该函数,而这个函数就在后台默默的执行,如果函数副作用很大,你会发现你倒霉了。

# 1

defia

哦,read不能用select,糊涂了 系统的read都是有超时设定的, 如果你自己的read就读到chan里,用别的goroutine,select从chan里取,超时直接关闭了连接呗

# 2

David

如果你的 read 操作没设计成可以通过某种方式中断的,你只能让它自己继续跑,直到自己返回之后被 GC 掉。Go 里面没有 interrupt go-routine 的操作。如果不希望这样,只能改 read 的设计。

# 3

snake117

@David 我自己的read当然可以设计一下。

不过难保我们会遇到要封装第三方包的read方法的情况。

比如之前的net.http.Client.Body的Read方法,这个方法可是会一直阻塞直到出错的。好在现在Client添加了Timeout字段。

我也是在尝试封装Read时发现这个问题的。

# 4

gvforjob

net.Conn.Read(buf []byte) (n int, err error)就是一直阻塞的,这个该怎么设计我们自己的逻辑来主动关闭掉这个 conn
我见过有的是在for循环每次Read之前调用一次SetDeadline(time time.time),这样子最多就阻塞一段时间,然后就可以通过channel来关闭。这样对性能有没有影响?

# 5

stevewang

可以在另外一个goroutine里关闭连接,这会导致Read返回error。

# 6