Trying to launch an external editor from within a Go program
Apparently, you have to set Stdin
, Stdout
and Stderr
on the Cmd
object to os.Std(in|out|err)
. Like this (assuming that the object is called cmd
):
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Credit for solving this goes to the guys on #go-nuts on freenode.
Calling an external command in Go
You need to use the exec package : start a command using Command and use Run
to wait for completion.
cmd := exec.Command("yourcommand", "some", "args")
if err := cmd.Run(); err != nil {
fmt.Println("Error: ", err)
}
If you just want to read the result, you may use Output instead of Run
.
How do I open a file with a text editor in Go?
You should call exec.Command
on a string whose content is a executable command path, with some arguments for this command as other parameters, like:
// shortcut for command in ENV PATH
//exepath := "notepad"
exepath := "C:\\Windows\\system32\\notepad.exe"
file := "H:\\code\\txt_projects\\hello6.txt"
cmd := exec.Command(exepath, file)
Refer to document.
os.Wait() does not wait for program termination in golang
Shouldn't cmd.Wait() be handling this?
Yes, and it does. Go waits as intended, it's your invocation of /usr/local/bin/code
which is incorrect, and does not wait. The default behavior of code
is to exit immediately after spawning the VSCode window. It does not wait for the window to close, and so Go cannot wait for the window to close.
Try simply typing code
in your terminal. You'll find that it exits immediately, even thought your VSCode window is still open.
To make code
block until the editor window is closed (thereby allowing Go to wait), you need to pass the -w
or --wait
flag to it. Again, try code -w
in your terminal. You'll find the terminal command blocks until the VSCode window is closed.
Practically, you only need to change this...
cmd := exec.Command("/usr/local/bin/code", fpath)
to this:
cmd := exec.Command("/usr/local/bin/code", "-w", fpath)
// or
// cmd := exec.Command("/usr/local/bin/code", "--wait", fpath)
VSCode: Could not import Golang package
This happens to me in a few specific situations. This is my troubleshooting process :
Did you run
go get github.com/gomodule/redigo/redis
?Sometimes I have a similar issue when I open my editor in a root different than my project.
. <- editor open here
|
|_Folder
| main.go
Make sure your tools are up to date: run
ctrl
+shift
+p
, typeGo
and choseInstall/Update tools
.Try moving your project out of the GOPATH, and setting up go.mod for it.
Restart the editor
How do you open an external Vim editor containing the active Eclipse editor file
There's two ways to do this, the canonical way, and the hack. First:
The Canonical Way
- Window > Preferences... Fold out General > Editors > File Associations.
- Choose the file type you want to edit
- Click the "Add" button beside the "Associated editors" box.
- Click "External programs" and "Browse...", then find gvim, or enter /usr/bin/gvim, or generally make it go to gvim.
Now, files of that type should show up in an external vim instance. Awesome, right? But that doesn't solve your problem of pushing the current buffer out to vim.
The Hack
Instead, we're going to set vim as a "build tool", and have eclipse send it the current file as arguments. This may have some unaffected side-effects, based on your project settings, but look into them carefully if you experience things like unexpected re-building of your files.
- Run > External Tools > External Tools Configuration...
- Select "Program" on the left and click the "New" icon.
- Enter "Send to vim" for the Name
- Enter "/usr/bin/gvim" (or whatever your path is) for the Location
- Under "Working Directory" enter
${project_loc}
(this is a variable representing your project's top directory) - Under arguments enter
${resource_loc}
(this represents your current resource's path) - On the "Build" tab, un-check "Build before Launch" (unless you really want that)
- On the Common tab, check "External Tools" under the "Display in favorites menu"
You should be all set! Now you can send your file to vim by using the menu
Run > External Tools > Send to vim
If you want to get fancy, you can even add a button to your toolbar.
Be advised, I've used gvim in the examples. If you'd like to use terminal vim, you'll have to call it appropriately based on the terminal you're using. For xterm, this would be /usr/bin/xterm -e /usr/bin/vim
, instead of /usr/bin/gvim
How to read/write from/to a file using Go
Let's make a Go 1-compatible list of all the ways to read and write files in Go.
Because file API has changed recently and most other answers don't work with Go 1. They also miss bufio
which is important IMHO.
In the following examples I copy a file by reading from it and writing to the destination file.
Start with the basics
package main
import (
"io"
"os"
)
func main() {
// open input file
fi, err := os.Open("input.txt")
if err != nil {
panic(err)
}
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()
// open output file
fo, err := os.Create("output.txt")
if err != nil {
panic(err)
}
// close fo on exit and check for its returned error
defer func() {
if err := fo.Close(); err != nil {
panic(err)
}
}()
// make a buffer to keep chunks that are read
buf := make([]byte, 1024)
for {
// read a chunk
n, err := fi.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
// write a chunk
if _, err := fo.Write(buf[:n]); err != nil {
panic(err)
}
}
}
Here I used os.Open
and os.Create
which are convenient wrappers around os.OpenFile
. We usually don't need to call OpenFile
directly.
Notice treating EOF. Read
tries to fill buf
on each call, and returns io.EOF
as error if it reaches end of file in doing so. In this case buf
will still hold data. Consequent calls to Read
returns zero as the number of bytes read and same io.EOF
as error. Any other error will lead to a panic.
Using bufio
package main
import (
"bufio"
"io"
"os"
)
func main() {
// open input file
fi, err := os.Open("input.txt")
if err != nil {
panic(err)
}
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()
// make a read buffer
r := bufio.NewReader(fi)
// open output file
fo, err := os.Create("output.txt")
if err != nil {
panic(err)
}
// close fo on exit and check for its returned error
defer func() {
if err := fo.Close(); err != nil {
panic(err)
}
}()
// make a write buffer
w := bufio.NewWriter(fo)
// make a buffer to keep chunks that are read
buf := make([]byte, 1024)
for {
// read a chunk
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
// write a chunk
if _, err := w.Write(buf[:n]); err != nil {
panic(err)
}
}
if err = w.Flush(); err != nil {
panic(err)
}
}
bufio
is just acting as a buffer here, because we don't have much to do with data. In most other situations (specially with text files) bufio
is very useful by giving us a nice API for reading and writing easily and flexibly, while it handles buffering behind the scenes.
Note: The following code is for older Go versions (Go 1.15 and before). Things have changed. For the new way, take a look at this answer.
Using ioutil
package main
import (
"io/ioutil"
)
func main() {
// read the whole file at once
b, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
// write the whole body at once
err = ioutil.WriteFile("output.txt", b, 0644)
if err != nil {
panic(err)
}
}
Easy as pie! But use it only if you're sure you're not dealing with big files.
Related Topics
Can't Access Publicly Exposed Docker Container Port from External Machine, Only from Localhost
Gnu Time and Formatting Output
Extract Lines When Column K Is Empty with Awk/Perl
How to Disable Non-Breaking Space with Altgr+Space
How to Install Devtools Package for R Studio Mounted on Linux Redhat Server
Version Control System Which Keeps Track of Individual Files
Setting CPU Affinity for Linux Kernel, Not Process
How to Build Git with Static Linking
Linux: How to Enable Execute in Place (Xip) for Ramfs/Tmpfs
How to Diff Two Sections of The Same File
Bash Will Not Auto-Complete (Tab) with Files
Copy Lines Containing Word from One File to Another File in Linux
How to Build The Elf Interpreter (Ld-Linux.So.2/Ld-2.17.So) as Static Library