在 Go 协程中更改目录

3

我正尝试在go协程中切换到x目录。现在,我想使用另一个go协程将工作目录更改为y目录。这个第二个go协程对第一个go协程的执行会产生影响吗?希望能够在做类似任务时引入并行性。如果它确实改变了工作目录,那么应该采用什么替代方法(分叉...)?


3
工作目录是进程的属性,goroutine无法更改目录。 - JimB
4
甚至更糟糕的是:这是在Unix系统上线程的一个属性,由于goroutine可以在多个不同的线程上运行,如果你的goroutine被移动,你会发现当前工作目录已经改变。 - Evan
那正是我所想的,那么唯一的选择就是分叉,我猜测是这样吧? - Rohan Nahata
你不能fork一个Go进程。唯一明智的管理方式是使用绝对路径,或者可能逐个更改目录(chdir)。 - JimB
2个回答

5

如评论中所述,在每个goroutine中跟踪当前工作目录会导致问题。

尝试使用filepath.Abs来捕获绝对目录并存储它。然后,每个goroutine可以在自己的目录上操作,而不必担心在幕后被“切换”。只需确保没有多个goroutine意外修改同一文件。

编辑:根据@Evan的评论删除了一大段文本。请使用绝对路径 :p


根据我的评论,你不能依赖当前工作目录在一行和下一行之间保持不变,因为你的 goroutine 可以在任何时候重新调度到具有不同工作目录的不同线程上。因此,我不知道在 Go 中有任何可靠处理当前工作目录的方法。 - Evan
@Evan:那不正确。Go提供了os.Chdir,如果操作系统支持它(我相信所有支持的操作系统都支持),则已实现。如果有的话,您可以使用它。 - JimB

1
@Evan指出了尝试使用“更改工作目录”(CWD)系统调用存在根本性缺陷。
我相信@Evan是正确的,CWD是某些操作系统上的线程属性。
正如@Evan所指出的那样,goroutine可能会被重新调度(例如在函数调用、通道访问或系统调用时)到不同的线程上。
这意味着,如果Go的运行时选择在不同的线程上重新调度goroutine,则可能无法更改CWD(如果Chdir()可以更改线程的CWD),因为它的CWD可能会隐形和不可预测地更改。
编辑:我不希望Chdir()做任何除更改进程的CWD之外的事情。但是,该包的文档没有提到“进程”。
更糟糕的是,运行时可能会在发布时更改工作方式。
更糟糕的是,这将非常难以调试。这可能是一个“海森堡问题”,任何尝试调试它的尝试(例如通过调用函数,运行时可能将其用作重新调度点)实际上可能以不可预测的方式改变行为。

跟踪绝对路径名。这是明确的,清晰的,甚至可以在协程之间工作,而不需要任何同步。因此,它更简单,更容易测试和调试。


Go语言提供了os.Chdir函数,它可以在支持更改进程工作目录的任何平台上实现。如果有这个函数,使用它就不是问题。 - JimB
@JimB - 我已经查看了文档,似乎没有关于如何实现Chdir()的保证。我非常同意仅更改进程当前工作目录而不更改线程当前工作目录是一个好的/明智的选择。然而,这个选择并没有明确说明,这会让我对在跨版本和平台上依赖它感到紧张。 - gbulmer
大多数事情的实现方式没有保证,文档也不必说明什么时候出现问题。如果 os.Chdir 在某些情况下无法正常工作,则需要将其记录在文档中。如果您有一个能够演示问题的测试用例,请随时提交问题。 - JimB
顺便提一下,POSIX线程保证所有线程共享相同的当前目录,并且该目录是内核中的进程属性。如果在某个新环境中不是这种情况,os.Chdir和syscall.Chdir将不存在。 - JimB
os.Chdir是被良好定义的,并且它的实现方式与支持多个操作系统和架构是兼容的。如果一个操作系统不支持它,就像许多其他特定于系统的系统调用一样,它将不会被实现(或者它将返回一个错误)。 - JimB
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接