从Go程序内部调用源

从Go程序内部调用源,go,Go,为了好玩和更好地学习围棋,我尝试在围棋中重新实现抗原 问题是:source是一个shell内置函数,所以我不能用os/execCommand函数调用它,因为它需要在路径中有一个可执行文件 我该怎么做?而且,是否可以使go程序内部的源代码影响用户shell?您可以直接在终端设备中写入命令。但是,要做到这一点,首先你需要知道哪个设备正在使用用户。执行程序的脚本可以作为解决方案 #!/bin/bash echo Running from foo script, pid = $$ go run foo.

为了好玩和更好地学习围棋,我尝试在围棋中重新实现抗原

问题是:
source
是一个shell内置函数,所以我不能用
os/exec
Command
函数调用它,因为它需要在
路径中有一个可执行文件


我该怎么做?而且,是否可以使go程序内部的
源代码影响用户shell?

您可以直接在终端设备中写入命令。但是,要做到这一点,首先你需要知道哪个设备正在使用用户。执行程序的脚本可以作为解决方案

#!/bin/bash
echo Running from foo script, pid = $$
go run foo.go `tty`
然后,程序必须将命令写入终端设备

package main

import (
    "C"
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func main() {
    // Get tty path
    if len(os.Args) < 2 {
        fmt.Printf("no tty path\n")
        os.Exit(1)
    }
    ttyPath := os.Args[1]

    // Open tty
    tty, err := os.Open(ttyPath)
    if err != nil {
        fmt.Printf("error opening tty: %s\n", err.Error())
        os.Exit(2)
    }
    defer tty.Close()

    // Write a command
    cmd := "echo Hello from go, pid = $$\n"
    cmdstr := C.CString(cmd)
    cmdaddr := uintptr(unsafe.Pointer(cmdstr))
    for i := range []byte(cmd) {
        _, _, err := syscall.Syscall(syscall.SYS_IOCTL, tty.Fd(), syscall.TIOCSTI, cmdaddr+uintptr(i))
        if uintptr(err) != 0 {
            fmt.Printf("syscall error: %s\n", err.Error())
            os.Exit(3)
        }
    }
}

请注意,我是使用
/
而不是
源代码执行脚本的,因此脚本的PID不同。但后来,go程序执行的命令具有相同的PID。

即使可以调用“源”,也不能更改父进程环境。你到底想达到什么效果?Sad:/Antigen是一个针对ZSH的插件管理器。。。所以,基本上,它是git拉取存储库并获取*.plugin.zsh文件的源代码…有什么可悲的?这就是贝壳的工作原理。抗原的全部目的是在你的外壳中执行外壳代码。是的,但它很慢。我对它进行了一点黑客攻击,得到了一个比antigen快5倍的“简化”版本:如果有真正的工作可以用Go加速(我根本没有读过代码),你可以在stdout上输出你需要的最终变量、函数def等,并将Go命令封装在一个
eval
中,您的示例在我尝试的任何系统上都不起作用(我认为需要刷新输入队列,我得到的只是一个
e
)。但是,如果要将其包装在shell脚本中,为什么不输出shell可以评估的内容呢?另外,
fmt.Errorf
只创建一个
error
值,它不会打印任何内容。@JimB抱歉,我忘记了
syscall.syscall
函数即使没有错误也会返回错误。现在应该可以了。哦,当然可以。我也错过了它,即使当我看到errno==0时。无论如何,如果我必须按照这些思路做一些事情,我还是宁愿使用stdout和
eval
。干得好!我最终使用了一种不同的方法。无论如何谢谢你!