我想从另一个go程序中执行另一个go程序并给它args,如下所示:
1 2 3 4 | package main func main() { //here I want to call a specific go file, e.g. test.go with args } |
test.go
1 2 3 4 | package main func main(x int) { //do stuff with x } |
我不想发送一个int作为arg,但像http.ResponseWriter
我想到的解决方案,但它不会很好:
谢谢你的回答:D
- 可能重复如何在golang中使用自定义包?
- 它不是重复的,你提到的问题想要导入一个go源文件,这在程序运行之前已经知道,而我想加载一个go源文件/编译文件,并且只在运行时获取文件名。
有许多方法可以实现这种互操作性:
1-如果你有双方的源文件,我建议使用标准的golang包(Lib)调用,而不是互操作性。
2-使用"os / exec":如果你没有源码,而你只有二进制,
或者您可以通过文件或文本args传递args:
你可以通过这样的args:
1 2 3 4 5 6 7 8 9 10 11 | package main import ( "fmt" "os" ) func main() { fmt.Println(os.Args[0]) // fileNameAndPath } |
或使用"flag"std lib:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // flags.exe -h package main import ( "flag" "fmt" ) func main() { namePtr := flag.String("name","AR","name") agePtr := flag.Int("age", 3700,"age") flag.Parse() fmt.Println(*namePtr, *agePtr) //AR 3700 } /* Usage of flags.exe: -age int age (default 3700) -name string name (default"AR") */ |
这将提供-h的帮助。
你可以像这样调用另一个二进制程序或golang编译器:
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main import ( "log" "os/exec" ) func main() { cmnd := exec.Command("main.exe","arg") //cmnd.Run() // and wait cmnd.Start() log.Println("log") } |
3-另一种方法是使用stdin / stdout调用外部程序。
通过这种方式,您可以通过stdin / out发送二进制数据:
这里文件"a"调用二进制文件"b"并通过stdin / stdout发送和接收:
这是我的转换:
http://erlang.org/doc/tutorial/c_port.html
(你可以使用os命名管道)
档案a:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | // a package main import ( "fmt" "log" "os/exec" "runtime" "time" ) var cout chan []byte = make(chan []byte) var cin chan []byte = make(chan []byte) var exit chan bool = make(chan bool) func Foo(x byte) byte { return call_port([]byte{1, x}) } func Bar(y byte) byte { return call_port([]byte{2, y}) } func Exit() byte { return call_port([]byte{0, 0}) } func call_port(s []byte) byte { cout <- s s = <-cin return s[1] } func start() { fmt.Println("start") cmd := exec.Command("../b/b") stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } stdout, err2 := cmd.StdoutPipe() if err2 != nil { log.Fatal(err2) } if err := cmd.Start(); err != nil { log.Fatal(err) } defer stdin.Close() defer stdout.Close() for { select { case s := <-cout: stdin.Write(s) buf := make([]byte, 2) runtime.Gosched() time.Sleep(100 * time.Millisecond) stdout.Read(buf) cin <- buf case b := <-exit: if b { fmt.Printf("Exit") return //os.Exit(0) } } } } func main() { go start() runtime.Gosched() fmt.Println("30+1=", Foo(30)) //30+1= 31 fmt.Println("2*40=", Bar(40)) //2*40= 80 Exit() exit <- true } |
文件b:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | // b package main import ( "log" "os" ) func foo(x byte) byte { return x + 1 } func bar(y byte) byte { return y * 2 } func ReadByte() byte { b1 := make([]byte, 1) for { n, _ := os.Stdin.Read(b1) if n == 1 { return b1[0] } } } func WriteByte(b byte) { b1 := []byte{b} for { n, _ := os.Stdout.Write(b1) if n == 1 { return } } } func main() { var res byte for { fn := ReadByte() log.Println("fn=", fn) arg := ReadByte() log.Println("arg=", arg) if fn == 1 { res = foo(arg) } else if fn == 2 { res = bar(arg) } else if fn == 0 { return //exit } else { res = fn //echo } WriteByte(1) WriteByte(res) } } |
4 - 另一种方法是使用"net / rpc",这是从另一个程序调用另一个函数的最佳方法。
样品:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | // rpc package main import ( "fmt" "net" "net/rpc" "runtime" "sync" ) var wg sync.WaitGroup type Server struct{} func (this *Server) Add(u [2]int64, reply *int64) error { *reply = u[0] + u[1] return nil } func server() { fmt.Println("server: Hi") rpc.Register(new(Server)) ln, err := net.Listen("tcp","127.0.0.1:12345") if err != nil { fmt.Println(err) return } for { c, err := ln.Accept() if err != nil { continue } go rpc.ServeConn(c) } } func client() { wg.Add(1) c, err := rpc.Dial("tcp","127.0.0.1:12345") if err != nil { fmt.Println(err) return } fmt.Println("Connected...") var result int64 err = c.Call("Server.Add", [2]int64{10, 20}, &result) if err != nil { fmt.Println(err) } else { fmt.Println("Server.Add(10,20) =", result) } wg.Done() } func main() { go server() runtime.Gosched() go client() runtime.Gosched() wg.Wait() fmt.Println("Bye") } /*output: server: Hi Connected... Server.Add(10,20) = 30 Bye */ |
- exec.Command()真的可以执行一个带有http.ResponseWriter等参数的程序吗?此外,我只在运行时获取文件名,这就是为什么如果我正确理解你的意思,第一个解决方案将无法工作。
- 如果你为http.ResponseWriter提供一些示例代码会更好,我认为第三种方式更适合这种情况,我会尽快添加样本
- @LucaS。您无法序列化http.ResponseWriter,因为它的接口,包实现包含状态,并且它处理网络连接。
- 我们走了:pastebin.com/3T1aw1xC
- 你有双方的来源吗?
- 我还没有编写动态页面,因为我不知道如何获得ResponseWriter和请求页面,没有这些页面将毫无价值。
- 有什么理由你使用两个单独的程序
- 对于某些可能有用的页面,但是当我使用单独的程序获得许多动态页面时会更清楚。
- 所以你不需要发送http.ResponseWriter。在一台计算机内的两个程序之间进行通信的最佳方式是使用管道甚至TCP,这种方式非常简单。但是,如果从另一个程序调用另一个函数"net / rpc"是合适的方式,我想。
- 好,谢谢!我可能会这样做。
使用
1 2 3 4 | output, err := exec.Command("go","run","/file/path/to/open").Output() if err == nil { w.Write(output) // write the output with ResponseWriter } |
Go不会通过
在我看来,你正试图在Go中使用PHP概念,这不会很好。相反,您应该使用模板和静态文件来实现动态网站。查看包
- 好吧,我有点尝试在Go中使用PHP概念,但文本/模板不符合我的标准,例如我需要根据文件和那些东西重定向
为要从其他文件运行的程序包创建executabl文件。提供要在
档案A.
1 2 3 4 5 6 7 8 9 | package a import"fmt" func main(){ for i:=0;i<10;i++{ fmt.Println(fmt.Sprintf("Process: %d", i)) } } |
为上面的文件创建二进制/可执行文件。该文件将位于包内,因此请转到包并运行可执行文件。
1 | go build github.com/user/a/a.go // or whatever be your GOPATH for executables to create a binary file |
下面是linux系统中二进制文件的情况。
档案B.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package b import ( "fmt" "os/exec" ) func main(){ // come out of package b and then go inside package a to run the executable file as cmd := exec.Command("../a/a.go") if err := cmd.Run(); err != nil{ fmt.Println(err) } } |