gpt4 book ai didi

go - 用cgo编译出错

转载 作者:数据小太阳 更新时间:2023-10-29 03:15:07 25 4
gpt4 key购买 nike

因此,我试图在不忙等待的情况下从 stdin 读取,忽略 EOF,因为在我的案例中,客户端会来来去去。在 C 中,我会使用简单的 select() 或 poll(),但我正在尝试学习 Go,但我对缺少 select() 或 poll() 感到非常沮丧。我找不到在 Go 中使用 select 和 channels 的好方法,因为 Read() 将在 EOF 上立即返回,而我又回到了忙碌的等待状态。 syscall.Select() 似乎是最好的方法,但 Go 并没有费心去实现 FD_SET! 感叹

所以,我正在尝试使用 cgo。

package main

/*
#include <stdlib.h>
#include <sys/select.h>
void _FD_SET(int sysfd, void *set) {
FD_SET(sysfd, (fd_set*)set);
}
*/
import "C"

import (
"unsafe"

但是当我尝试在我的 Mac 上构建它时,我明白了。

# github.com/msoulier/mlogd
could not determine kind of name for C._FD_SET

clang errors for preamble:
src/github.com/msoulier/mlogd/mlogd.go:6:14: error: expected identifier or '('
void _FD_SET(int sysfd, void *set) {
^
src/github.com/msoulier/mlogd/mlogd.go:6:14: error: expected ')'
src/github.com/msoulier/mlogd/mlogd.go:6:13: note: to match this '('
void _FD_SET(int sysfd, void *set) {
^
2 errors generated.

如果我将导入合并在一起,那么大部分错误都会消失。

package main

/*
#include <stdlib.h>
#include <sys/select.h>
void _FD_SET(int sysfd, void *set) {
FD_SET(sysfd, (fd_set*)set);
}
*/
import (
"C"
"unsafe"
"syscall"

但是还有一个。

# github.com/msoulier/mlogd
could not determine kind of name for C._FD_SET

所以,我在这里寻找两件事。

  1. 为什么我在这里对 cgo 做错了?根据我的阅读,这应该“正常工作”。
  2. 有没有更好的方法可以无限期地从 stdin 读取数据,而无需忙于等待并忽略 EOF?

我的环境。

msoulier@merlin:~/work/go$ go version
go version go1.6.2 darwin/amd64
msoulier@merlin:~/work/go$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/msoulier/work/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.6.2/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.6.2/libexec/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT="1"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"

提前致谢。必须比这更简单。

我通过 select 走到了这一步。

// loop forever - we expect to be killed with a SIGTERM or SIGINT
for {
logger.Debug("going into select on stdin")
var r_fdset syscall.FdSet
for i := 0; i < 16; i++ {
r_fdset.Bits[i] = 0
}
r_fdset.Bits[0] = 1
selerr := syscall.Select(1, &r_fdset, nil, nil, nil)
if selerr != nil {
logger.Warning(selerr)
}

但即使输入用完它也会立即返回。

迈克

最佳答案

在 Go 中,您执行阻塞操作。无处不在。

您将那些阻塞操作放在 goroutine 中,这些 goroutine 就像绿色线程/纤程一样。它们由 Go 运行时调度,可能在真实线程上,也可能共享线程。

然后您使用 channel 与您的 Go 程序的其他部分对话。

关于标准输入在 EOF 后始终可读的问题,请停止阅读。我的阅读器 goroutine 下面只是退出。

这里,有一个我刚刚写的例子:

package main

import (
"fmt"
"io"
"os"
"time"
)

func main() {
var err error
ch1 := make(chan []byte)
ch2 := make(chan int)
var buf []byte
var i int
var ok bool

go reader(ch1)
go counter(ch2)

for {
select {
case buf, ok = <-ch1:
if ok {
_, err = os.Stdout.Write([]byte("input: "))
_, err = os.Stdout.Write(buf)
}

case i, ok = <-ch2:
if ok {
_, err = fmt.Println("count", i)
}
}
if err != nil {
fmt.Println("error", err)
}
if !ok {
break
}
}
}

func counter(ch chan<- int) {
i := 0
for i < 5 {
i++
ch <- i
time.Sleep(time.Second)
}
close(ch)
}

func reader(ch chan<- []byte) {
var r int
var err error
for {
buf := make([]byte, 4000)
r, err = os.Stdin.Read(buf)
if r > 0 {
ch <- buf[:r]
}
if err != nil {
fmt.Println("read error", err)
if err == io.EOF {
break
}
// Or really just about any error on read is fatal
break
}
}
close(ch)
}

关于go - 用cgo编译出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38022991/

25 4 0
文章推荐: macos - 如何对 Go 工作区进行碎片化
文章推荐: javascript - document.getElementByID 不是函数
文章推荐: javascript -