如何在Go中启动一个不是文件的进程(例如打开一个网页)

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

How can I launch a process that is not a file in Go (e.g. open a web page)

问题

c, err := exec.Command("xdg-open", "http://localhost:4001").Output()
if err != nil {
fmt.Printf("ERROR: %v, %v\n", err, c)
} else {
fmt.Printf("OK:%v\n", c)
}

英文:

I want to open a web browser:

c, err := exec.Command("http://localhost:4001").Output()
if err != nil {
	fmt.Printf("ERROR: %v, %v\n",err,c)
} else {
	fmt.Printf("OK:%v\n",c)
}

and I get the error

ERROR: exec: "http://localhost:4001": file does not exist

Edit: What I want to achieve is the same as in Windows and C# when you do:

Process.Start("http://localhost:4001")

With it a new instance of your default browser will launch showing the URL

答案1

得分: 15

"http://localhost:4001/"是一个URL,它不能被执行,但是你可以执行一个网络浏览器(例如firefox)并将URL作为第一个参数传递。

在Windows、OS X和Linux上,存在可以用来启动默认网络浏览器的辅助程序。我猜在FreeBSD和Android上也有类似的东西,但我不确定。以下代码片段应该适用于Windows、OS X和大多数Linux发行版:

var err error
switch runtime.GOOS {
case "linux":
    err = exec.Command("xdg-open", "http://localhost:4001/").Start()
case "windows", "darwin":
    err = exec.Command("open", "http://localhost:4001/").Start()
default:
    err = fmt.Errorf("unsupported platform")
}
英文:

"http://localhost:4001/" is a URL, it can not be executed, but you can execute a web browser (e.g. firefox) and pass the URL as first argument.

On Windows, OS X, and Linux helper programs exist which can be used to start the default web browser. I guess there is a similar thing for FreeBSD and Android, but I am not sure about it. The following snippet should work on Windows, OS X, and most Linux distros:

var err error
switch runtime.GOOS {
case "linux":
    err = exec.Command("xdg-open", "http://localhost:4001/").Start()
case "windows", "darwin":
    err = exec.Command("open", "http://localhost:4001/").Start()
default:
    err = fmt.Errorf("unsupported platform")
}

答案2

得分: 6

在Windows下使用:

exec.Command("cmd", "/c", "start", "http://localhost:4001/").Start()
英文:

Under Windows using:

exec.Command("cmd", "/c", "start", "http://localhost:4001/").Start()

答案3

得分: 3

在tux21b的答案中,使用

exec.Command("open", "http://localhost:4001/").Start()

在Windows上对我不起作用。然而,以下代码可以:

exec.Command(`C:\Windows\System32\rundll32.exe`, "url.dll,FileProtocolHandler", "http://localhost:4001/").Start()
英文:

Using

exec.Command("open", "http://localhost:4001/").Start()

in tux21b's answer above didn't work for me on Windows. However this did:

exec.Command(`C:\Windows\System32\rundll32.exe`, "url.dll,FileProtocolHandler", "http://localhost:4001/").Start()

答案4

得分: 2

// Commands返回一个用于打开URL的可能命令列表。
func Commands() [][]string {
var cmds [][]string
if exe := os.Getenv("BROWSER"); exe != "" {
cmds = append(cmds, []string{exe})
}
switch runtime.GOOS {
case "darwin":
cmds = append(cmds, []string{"/usr/bin/open"})
case "windows":
cmds = append(cmds, []string{"cmd", "/c", "start"})
default:
cmds = append(cmds, []string{"xdg-open"})
}
cmds = append(cmds, []string{"chrome"}, []string{"google-chrome"}, []string{"firefox"})
return cmds
}

// Open尝试在浏览器中打开URL,并报告是否成功。
func Open(url string) bool {
for _, args := range Commands() {
cmd := exec.Command(args[0], append(args[1:], url)...)
if cmd.Start() == nil {
return true
}
}
return false
}

英文:

https://github.com/golang/go/blob/33ed35647520f2162c2fed1b0e5f19cec2c65de3/src/cmd/internal/browser/browser.go

// Commands returns a list of possible commands to use to open a url.
func Commands() [][]string {
	var cmds [][]string
	if exe := os.Getenv("BROWSER"); exe != "" {
		cmds = append(cmds, []string{exe})
	}
	switch runtime.GOOS {
	case "darwin":
		cmds = append(cmds, []string{"/usr/bin/open"})
	case "windows":
		cmds = append(cmds, []string{"cmd", "/c", "start"})
	default:
		cmds = append(cmds, []string{"xdg-open"})
	}
	cmds = append(cmds, []string{"chrome"}, []string{"google-chrome"}, []string{"firefox"})
	return cmds
}

// Open tries to open url in a browser and reports whether it succeeded.
func Open(url string) bool {
	for _, args := range Commands() {
		cmd := exec.Command(args[0], append(args[1:], url)...)
		if cmd.Start() == nil {
			return true
		}
	}
	return false
}

答案5

得分: 1

"http://localhost:4001" 不是一个进程,也不是可执行文件,它只是一个URL。

看起来你正在尝试获取一个URL。如果是这样,请考虑使用 net/http

英文:

"http://localhost:4001" is not a process, nor executable, ... it's just a URL.

It looks like you're trying to fetch a URL. If so, consider using net/http.

答案6

得分: 0

对于Windows,创建一个像这样的文件:

//go:generate mkwinsyscall -output zweb.go web.go
//sys shellExecute(window int, verb string, file string, arg string, dir string, showCmd int) (err error) = shell32.ShellExecuteW
package main
const sw_shownormal = 1

func main() {
   shellExecute(0, "", "https://stackoverflow.com", "", "", sw_shownormal)
}

然后进行构建:

go mod init web
go generate
go mod tidy
go build

https://pkg.go.dev/golang.org/x/sys/windows/mkwinsyscall

英文:

For Windows, create a file like this:

//go:generate mkwinsyscall -output zweb.go web.go
//sys shellExecute(window int, verb string, file string, arg string, dir string, showCmd int) (err error) = shell32.ShellExecuteW
package main
const sw_shownormal = 1

func main() {
   shellExecute(0, "", "https://stackoverflow.com", "", "", sw_shownormal)
}

Then build:

go mod init web
go generate
go mod tidy
go build

https://pkg.go.dev/golang.org/x/sys/windows/mkwinsyscall

答案7

得分: -1

首先,我喜欢@tux21b提供的答案。但是这段代码存在一个微妙的问题:选择特定平台代码的条件逻辑将嵌入到目标可执行文件中。这意味着逻辑将存在于“windows”,“linux”,“darwin”或任何目标平台中。在这个特定的例子中,每个平台的代码只有一行。但是想象一下,当每个平台的代码达到100+行时会发生什么?目标可执行文件的大小将大幅增长。因此,与其为每个可能的平台都包含代码,不如在构建时只包含正确的代码。实际上,Go支持名为build tags的功能,它可以更精细地控制特定平台的代码。

例如,如果一个文件在包声明之前包含以下注释:

// +build linux darwin

当构建Linux或Mac OS X时,go build将只编译它。这意味着目标可执行文件将不包含任何外来平台的代码。

open-golang包提供了所问功能,但考虑了build tags

英文:

At first, I liked the answer provided by @tux21b. But there is a subtle problem with this code: conditional logic for selecting platform specific code will be embedded into target executable binary. It means that, the logic will be present in "windows", "linux", "darwin" or whatever the target platform. In this particular example the code is just one line per platform. But imagine, what happens when code would be 100+ lines per platform? The target executable will grow dramatically. So rather than include code for every possible platform, it is better to include just the right one at build time. Actually Go supports feature called build tags, which gives more fine-grained control over platform specific code.

For example, if a file contains this comment (before the package declaration):

// +build linux darwin

go build will compile it only when building for Linux or Mac OS X. It means the target executable will contain NO code for alien platforms.

open-golang package provides the questioned functionality, but with build tags in mind!

huangapple
  • 本文由 发表于 2012年4月30日 08:30:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/10377243.html
匿名

发表评论

匿名网友

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

确定