通道关闭后如何关闭程序

  • 本文关键字:关闭程序 通道 go channel
  • 更新时间 :
  • 英文 :


我正在尝试编写一个同时挖掘比特币块的程序。我已经设置好了,这样每个程序都有一个初始的起始随机数,每个随机数都是4ie的一小部分。2**64 - 1 (max number of uint64 type)/1或2或3或4.

只有一个矿工会遇到正确的nonce,当这种情况发生时,我希望它通过通道传递给矿工管理器,当这种情况发生时,我希望其他3个矿工停止他们正在做的事情。

唯一的问题是我不知道如何销毁一个正在运行的程序,或者是否有一种方法来做我所要求的。

func miner(blockNumber int, transactions string, previousHash string, zeroPrefix string, startNonce uint64, nonceChan chan uint64, hashChan chan string) {
var text string
var newHash string
for {
text = strconv.Itoa(blockNumber) + transactions + previousHash + strconv.FormatUint(startNonce, 10)
newHash = encrypt(text)
if startswith(newHash, zeroPrefix) {
nonceChan <- startNonce
hashChan  <- newHash
close(nonceChan)
close(hashChan)
break
} else {
startNonce++
}
}
}
func mine(blockNumber int, transactions string, previousHash string, zeroPrefix int) Block {
var prefixString string
var newHash string
var nonce uint64
var startNonce uint64
nonceChan := make(chan uint64)
hashChan := make(chan string)
for i := 0; i < zeroPrefix; i++ {
prefixString += "0"
}
start := time.Now()
for i := 0; i < 4; i++{
// This line is for deciding at what nonce value a miner should start at.
startNonce = uint64((float64(i) / 4) * math.Pow(2, 64))
go func() {
fmt.Println("Started miner with start nonce of", startNonce)
miner(blockNumber, transactions, previousHash, prefixString, startNonce, nonceChan, hashChan)
}()
}
nonce = <- nonceChan
newHash = <- hashChan
// Here is where I would like to destroy the other three miners
block := Block{
blockNumber,
transactions,
previousHash,
newHash,
nonce,
zeroPrefix,
time.Since(start),
}
return block
}

在函数中创建一个ctx, cancel := context.WithCancel(context.Background()),用于启动所有的goout程,并将其传递给所有的goout程(作为函数中的第一个参数)

当需要取消工作时,调用cancel函数。你可以这样做,例如在main函数收到结果后。

在每个例程中检查ctx.Done的选择(在for循环中):

select {
case <-ctx.Done():
return
default:
}
// continue mining

例子:

func miner(ctx context.Context, ...) {
defer func() {
// any necessary cleanup
}
for {
select {
case <-ctx.Done():
// abort was called for: exit
return
default:
}
// continue mining
}
}
func mine() {
// use a single channel to get the result. You could 
// block yourself if you use multiple channels
chResult := make(chan result)
// create context
ctx, cancel := context.WithCancel(context.Background())
for i := 0; i < 4; i++{
// ...
// pass the context into the miner
go miner(ctx, chResult, ...)
}
// block for first miner to be successful
res := <-chResult

// cancel the other routines
cancel()

// ...
}

result可以是:

struct result {
hash  string
nonce uint64
}

你可以使用context来处理go例程的终止。

context :包上下文定义了上下文类型,它在API边界和进程之间携带截止日期、取消信号和其他请求范围的值。

ctx, cancel := context.WithCancel(context.Background())用这个可以创建一个contextcancel函数。

只要在你的go例程中传递ctx and cancel,当你在任何go例程中完成时,只需调用cancel()func()。然后ctx.done()将为真,然后switch的第一种情况将为真,它将从所有go例程返回。


func miner( ctx context.Context,  blockNumber int, transactions string, previousHash string, zeroPrefix string, startNonce uint64, nonceChan chan uint64, hashChan chan string) {
var text string
var newHash string
for {
select {
case <-ctx.Done():  // if cancel() execute
return
default:
text = strconv.Itoa(blockNumber) + transactions + previousHash + strconv.FormatUint(startNonce, 10)
newHash = encrypt(text)
if startswith(newHash, zeroPrefix) {
nonceChan <- startNonce
hashChan  <- newHash
close(nonceChan)
close(hashChan)
break
} else {
startNonce++
}
}
}
}
func mine(blockNumber int, transactions string, previousHash string, zeroPrefix int) Block {
var prefixString string
var newHash string
var nonce uint64
var startNonce uint64
nonceChan := make(chan uint64)
hashChan := make(chan string)
for i := 0; i < zeroPrefix; i++ {
prefixString += "0"
}
start := time.Now()
ctx, cancel := context.WithCancel(context.Background())
for i := 0; i < 4; i++{
// This line is for deciding at what nonce value a miner should start at.
startNonce = uint64((float64(i) / 4) * math.Pow(2, 64))
go func(ctx context.Context) {
fmt.Println("Started miner with start nonce of", startNonce)
miner(ctx, blockNumber, transactions, previousHash, prefixString, startNonce, nonceChan, hashChan)
}(ctx)
}
nonce = <- nonceChan
newHash = <- hashChan
cancel()
// Here is where I would like to destroy the other three miners
block := Block{
blockNumber,
transactions,
previousHash,
newHash,
nonce,
zeroPrefix,
time.Since(start),
}
return block
}

最新更新