在Go语言中实现信号量的最佳方法是什么

cbeh67ev  于 2022-12-07  发布在  Go
关注(0)|答案(4)|浏览(145)

我有一个测试程序,我想从命令行运行程序的多个副本,我需要知道程序启动的第一个示例。在Dart中,我做了以下有人建议我做的事情:

RawServerSocket.bind("127.0.0.1", 8087)

如果失败了,我就知道另一个程序已经“锁定”了端口。这对我来说已经足够好地解决了这个问题。当程序终止或显式关闭套接字时,锁定就会被释放。
在围棋中如何才能达到类似的结果?

ojsjcaue

ojsjcaue1#

你不用说你使用的是哪个平台。如果你想跨平台,那么打开一个本地套接字的解决方案是非常简单的。下面是你在Go语言中如何做到这一点。

package main

import (
    "log"
    "net"
    "time"
)

func main() {
    ln, err := net.Listen("tcp", "127.0.0.1:9876")
    if err != nil {
        log.Fatal("Failed to get lock: ", err)
    }
    defer ln.Close()
    log.Print("Started")
    time.Sleep(time.Second * 10)
    log.Print("Ending")
}

不幸的是,在不使用套接字的情况下实现这一点的跨平台方式是相当困难的,并且将涉及两组代码,一组用于Unix之类的系统,另一组用于Windows。
请注意,病毒检查程序不喜欢在windows上打开侦听套接字的程序...

mf98qq94

mf98qq942#

“unix方法”是在/var/run/ .pid中创建一个pid文件。这就是我们在Docker www.example.com中的做法https://github.com/dotcloud/docker/blob/master/docker/docker.go#L91如果文件存在,则意味着程序已经启动。
我不建议使用bind方法,它会毫无意义地锁定端口,并且您无法确定其他程序是否正在使用该端口。

1u4esq0p

1u4esq0p3#

使用带有os.CREATE | os.O_EXCL标志的os.OpenFile()怎么样?

file, err := os.OpenFile("lock", os.O_CREATE | os.O_EXCL | os.O_RDWR, 0400)
if err != nil {
        // Someone else has acquired the lock.
}
defer file.Close()
defer os.Remove("lock") // Ignoring errors here!

我还没有编译或测试这一点,但它应该工作,在任何情况下,你得到的想法...

luaexgnf

luaexgnf4#

使用github.com/gofrs/flock包,使用类似于下面的代码来满足您的目的:

import "github.com/gofrs/flock"

fileLock := flock.New("/var/lock/go-lock.lock")

locked, err := fileLock.TryLock()

if err != nil {
    // handle locking error
}

if locked {
    // handle "first one in" case
    fileLock.Unlock()
} else {
    // handle subsequent cases
}

如需详细信息,请参阅https://github.com/gofrs/flock

相关问题