接收来自非通道类型 *bool 的值

huangapple go评论83阅读模式
英文:

Receive from non-chan type *bool

问题

我想将myapp变成守护进程,但是我遇到了一个大问题。我正在使用的通道的类型是chan struct{}。然而,使用getopt(flag包)时,我的标志的类型是*bool,所以我不知道如何修改myapp。

仅仅使用bool类型的通道是不够的。我确定有一个概念我不理解。我附上了代码:

package main

import (
	"os"
	"syscall"
	"time"
	
	"github.com/pborman/getopt/v2"
	"github.com/sevlyar/go-daemon"
)

var (
	done   = make(chan struct{})
	optQuit = make(chan struct{})
	optRun  = make(chan struct{})
)

func TermHandler(sig os.Signal) error {
	optQuit <- struct{}{}
	if sig == syscall.SIGQUIT {
		<-done
	}
	return nil
}

func main() {
	optHelp := getopt.BoolLong("help", 'h', "Help")
	optQuit := getopt.BoolLong("quit", 0, "Help")
	optRun  := getopt.BoolLong("run", 'r', "Help")
	
	if *optHelp {
		getopt.Usage()
		os.Exit(0)
	}

	// 创建pid文件
	cntxt := &daemon.Context{
		PidFileName: "/var/run/myapp.pid",
		PidFilePerm: 0644,
		WorkDir:     "./",
		Umask:       027,
		Args:        []string{"[Z]"},
	}

	if len(daemon.ActiveFlags()) > 0 {
		d, _ := cntxt.Search()
		daemon.SendCommands(d)
		return
	}
	d, err := cntxt.Reborn()
	if d != nil {
		return
	}
	if err != nil {
		os.Exit(1)
	}
	defer cntxt.Release()

	// 定义ticker
	ticker := time.NewTicker(time.Second)
	myapp := true
	
	// 循环
	for myapp {
		select {

		// Case sleep
		case <-ticker.C:
			time.Sleep(time.Second)

		// Case QUIT
		case <-optQuit:
			done <- struct{}{}
			myapp = false
			ticker.Stop()
			os.Exit(0)

		// Case RUN
		case <-optRun:
			// 执行一个goroutine...
		}
	}
}

使用go install命令,我看到了以下错误:

./main.go:72: invalid operation: <-optQuit (receive from non-chan type *bool)
./main.go:79: invalid operation: <-optRun (receive from non-chan type *bool)

我不知道我应该如何修改通道(done、optQuit的类型为struct{}),以解决这个问题...

附注:我向你展示了一个我做的示例。它作为守护进程运行,并且每分钟执行一次Writer()函数。然后,如果你输入zdaemon -z quit,应用程序会进行优雅关闭。你可以在你的机器上运行它:

https://play.golang.org/p/RVq7M7usEj

英文:

I want to daemonize myapp but I have one big problem. The channels I'm using are of type chan struct{}.
However, with the package getopt (flag package), my flags are of type *bool, so I don't know how can I modify myapp.

It's not enough with channels type bool. I'm sure there are a concept that I don't understand. I attach you the code:

package main
import (
&quot;os&quot;
&quot;syscall&quot;
&quot;time&quot;
&quot;github.com/pborman/getopt/v2&quot;
&quot;github.com/sevlyar/go-daemon&quot;
)
var (
done	= make(chan struct{})
optQuit = make(chan struct{})
optRun  = make(chan struct{})
)
func TermHandler(sig os.Signal) error {
optQuit &lt;- struct{}{}
if sig == syscall.SIGQUIT {
&lt;-done
}
return nil
}
func main() {
optHelp := getopt.BoolLong(&quot;help&quot;, &#39;h&#39;, &quot;Help&quot;)
optQuit := getopt.BoolLong(&quot;quit&quot;, 0, &quot;Help&quot;)
optRun  := getopt.BoolLong(&quot;run&quot;, &#39;r&#39;, &quot;Help&quot;)
if *optHelp {
getopt.Usage()
os.Exit(0)
}
// Create pid file
cntxt := &amp;daemon.Context{
PidFileName: &quot;/var/run/myapp.pid&quot;,
PidFilePerm: 0644,
WorkDir:     &quot;./&quot;,
Umask:       027,
Args:        []string{&quot;[Z]&quot;},
}
if len(daemon.ActiveFlags()) &gt; 0 {
d, _ := cntxt.Search()
daemon.SendCommands(d)
return
}
d, err := cntxt.Reborn()
if d != nil {
return
}
if err != nil {
os.Exit(1)
}
defer cntxt.Release()
// Define ticker
ticker := time.NewTicker(time.Second)
myapp := true
// Loop
for myapp {
select {
// Case sleep
case &lt;- ticker.C:
time.Sleep(time.Second)
// Case QUIT
case &lt;- optQuit:
done &lt;- struct{}{}
myapp = false
ticker.Stop()
os.Exit(0)
// Case RUN
case &lt;- optRun:
// Executes a goroutine...
}
}
}

With go install, I can see this errors:

./main.go:72: invalid operation: &lt;-optQuit (receive from non-chan type *bool)
./main.go:79: invalid operation: &lt;-optRun (receive from non-chan type *bool)

I don't know how I should modify the channels (done, optQuit of type struct{}), to resolve this...

P.S.: I show you an example that I did. It runs as daemon and each minute, it executes the function Writer().
After, if you type zdaemon -z quit, the app does a graceful shutdown. You can run it in your machines:

https://play.golang.org/p/RVq7M7usEj

答案1

得分: 0

你的主函数中的这两行代码遮盖了全局变量的声明:

optQuit := getopt.BoolLong("quit", 0, "Help")
optRun  := getopt.BoolLong("run", 'r', "Help")

如果你只是用它们来获得一个漂亮的用法,为什么不自己创建一个用法函数呢?

如果你坚持使用 getopt 来创建用法,可以这样做:

_ = getopt.BoolLong("quit", 0, "Help")
_ = getopt.BoolLong("run", 'r', "Help")

而不是赋值给变量。

在使用 *optHelp 之前,你还需要调用 getopt.Parse()

生成的消息

Usage: test [-hr] [--quit] [parameters ...]
-h, --help  Help
--quit  Help
-r, --run   Help

似乎不太有帮助。为什么不直接这样做:

fmt.Printf(`
Usage: test
This program will start a daemon service, which you can use like this ...
`)
英文:

Those two lines in your main function shadow your global variable declaration:

optQuit := getopt.BoolLong(&quot;quit&quot;, 0, &quot;Help&quot;)
optRun  := getopt.BoolLong(&quot;run&quot;, &#39;r&#39;, &quot;Help&quot;)

If you only use them, to get a nice usage, why not create a usage function
yourself?

If you insist on using getopt just to create a usage, do

_ = getopt.BoolLong(&quot;quit&quot;, 0, &quot;Help&quot;)
_ = getopt.BoolLong(&quot;run&quot;, &#39;r&#39;, &quot;Help&quot;)

instead.

You also need to call getopt.Parse() before using *optHelp.

The resulting message

Usage: test [-hr] [--quit] [parameters ...]
-h, --help  Help
--quit  Help
-r, --run   Help

seems to be less than helpful. Why not just do

fmt.Printf(`
Usage: test
This program will start a daemon service, which you can use like this ...
`)

答案2

得分: 0

你在全局定义了optQuit = make(chan struct{}),然后在main函数中将其遮蔽了:optQuit := getopt.BoolLong("quit", 0, "Help")

所以在main函数中,optQuit是一个bool类型,而不是一个chan类型。

请在main函数中删除这两行代码:

optQuit := getopt.BoolLong("quit", 0, "Help")
optRun  := getopt.BoolLong("run", 'r', "Help")
英文:

You define optQuit = make(chan struct{}) globally and then shadow it in main: optQuit := getopt.BoolLong(&quot;quit&quot;, 0, &quot;Help&quot;).

So in main optQuit is a bool, not a chan

Remove those two lines in main:

optQuit := getopt.BoolLong(&quot;quit&quot;, 0, &quot;Help&quot;)
optRun  := getopt.BoolLong(&quot;run&quot;, &#39;r&#39;, &quot;Help&quot;)

huangapple
  • 本文由 发表于 2017年6月20日 16:07:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/44647342.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定