如何启动Go中非文件的进程(例如,打开网页)

I want to open a web browser:

c, err := exec.Command("http://localhost:4001").Output()
if err != nil {
    fmt.Printf("ERROR: %v, %v
",err,c)
} else {
    fmt.Printf("OK:%v
",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

"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")
}

"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.

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\System32undll32.exe`, "url.dll,FileProtocolHandler", "http://localhost:4001/").Start()

Under Windows using:

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

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
}

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!