Sublime Forum

Run Golang project in Sublime Text 3 with output

#1

I cannot find a suitable solution for my needs with running a Go project inside a Sublime Text 3 and seeing it’s output in real-time.

If I try a build system from:

  1. GoSublime - I can use run, it even runs and stops, but there is no output, which I need. It appears only when I cancel build - it’s too late.
  2. Oficial Golang Build from Go developers - I can build the project, and that’s it. It allows to run 1 file (current) only, but I need the whole project. I’ve tried to use flags for run command and to add *.go, but then I get *.go: no such file or directory.

How do I see the output in real-time in one of these solutions? I’ve tried to create my own build system with shell_cmd = *go run .go, but stopping the process with Cancel build is not working then. May be you can explain how do I stop a running Go program? My mybuild.sublime-build is similar to this:

{
	"env": {
		"GOROOT": "/path/gosrc/go",
		"GOPATH": "/path/godev"
	},
	"path": "$PATH:/path/gosrc/go/bin",
	"working_dir": "/path/godev/src/github.com/vitute/program",
	"cmd": "go run *.go",
	"shell": true
}

…I can run Build and see the needed output, but how do I then stop runnning process?

P.S. Program is not just executing and exiting - it’s a service, so I should see the output when the needed actions happens.

0 Likes

#2

On a Mac, you can cancel a build with ^C or click the Tools menu. I’m sure there is something equivalent on Windows and Linux.

Also, make sure these are enabled in your Preferences.sublime-settings file, or you won’t see any output in the Build Panel.

    // Shows the Build Results panel when building. If set to false, the Build
    // Results can be shown via the Tools/Build Results menu.
    "show_panel_on_build": true,

    // Shows build errors just under the line on which they occur.
    "show_errors_inline": true,
0 Likes

#3

On Linux I also have Cancel Build , I can press it with my custom build system, on the background probably something happens, the menu button becomes disabled. But when I check my service - it’s still running. So ST3 didn’t kill that. So I’m not sure, what process ST is looking for to stop.

In Golang when you execute *go run .go - the OS process name won’t be go, but something else. Maybe Sublime Text is looking for go and can’t find it?

Do you have any suggestions about existing Go build systems?

With GoSublime I can press Build and Cancel Build too - it works, but there is no output in real-time, which I need

0 Likes

#4

The cancel build command terminates whatever external process it started, but it doesn’t kill any child processes that that process may have started, which may be at play here if the manner in which go run operates is to spawn an external process of some kind.

As the above github issue points out, the file Default/exec.py is what is used for build systems, and it captures and displays all output to stdout and stderr as it arrives. So if you’re not seeing any output at runtime but you see it when you cancel the build, it’s probably because whatever you’re running is buffering it’s output (possibly behind the scenes without you realizing it).

If that is the case, then Sublime won’t display the output until either the buffer in your program fills and writes the output (which could take a long while depending on buffer sizes and output frequency) or the task gets terminated (which is like an explicit flush).

I am by no means a Go expert (I more or less know that it exists), but using this build system:

{
    "shell_cmd": "go run ${file}",
    "selector": "source.go"
}

I can execute the following go program (under Linux) and I see the output appear one line per second, as one might expect:

package main

import "fmt"
import "time"

func main() {
    for i := 0 ; i < 10 ; i++ {
        time.Sleep(time.Second)
        fmt.Println("Hello world", i)
    }
}

Contrast that with this C program (again under Linux, using gcc):

#include <stdio.h>
#include <unistd.h>

int main (int argc, const char **argv)
{
    int i;
    for (i = 0 ; i < 10 ; i++)
    {
        sleep(1);
        printf("Hello world %d\n", i);
        // fflush(stdout);
    }

    return 0;
}

When I run this program as it stands, after 10 seconds all of the output lines appear in the output panel all at once. However, by uncommenting the flush line so that every time through the loop stdout gets flushed, the output appears at one line per second again.

People sometimes get confused because the same program executed directly from the terminal operates as they would expect it to work. For example the C program above, when executed from the terminal, outputs lines once per second despite the fact that the fflush call is commented out.

One reason for that is that the underlying libraries try to be smart about how they buffer the data based on how the program is run. When run interactively from a terminal, they assume you’re going to want to interact, and so they may choose a different buffering scheme. For example, on Linux stdout is line buffered when you run programs from the command line but fully buffered otherwise. Other operating systems may behave differently.

A good rule of thumb about output (any output, not just interactive stuff) is that if you want it to be fully represented at the output medium (file, screen, the other end of a socket connection) in some time specific way, you should either be using unbuffered output or explicitly doing a buffer flush at key points.

2 Likes

#5

There are a lot of problems with mybuild.sublime-build.

  1. You don’t need to set $GOROOT. When I see people setting $GOROOT, it usually means they’ve set up their Go environment incorrectly.
  2. If you’re new to Go, I encourage you to stick with the default $GOPATH of $HOME/go.
  3. go run is a convenient way to build+run Go code in a single command. Typically, you go run a single .go file, e.g. go run foo.go, where foo.go contains func main(). If foo.go needs code in other files to build correctly, you must pass those as well: go run foo.go pkg.go otherpkg.go
  4. If you’re setting "shell": True then you shouldn’t have to set anything in "env". The $GOPATH should be set by your shell config, e.g. .bashrc or .zshrc.

Here’s all you need to have a well-configured Go environment.

$HOME/
  go/
    bin/
    pkg/
    src/
      github.com/
        vitrute/
          myproject/
            foo.go

optional, but encouraged:

export GOPATH=$HOME/go

If I were you, I’d forget about build systems for the moment and concentrate on using the terminal commands (e.g. go build, go test). When you’ve got those down, then you’ll know the right shell commands to put in your .sublime-build file.

0 Likes

#6

@OdatNurd, Thanks, good explanation. New info:

  1. The plugin from Github you mentioned has solved the problem with cancelling the build. Now with my custom build system I can run the process, see the output, and cancel build. So the problem was with a child process. Maybe you have any info when/if this behavior will be by default? (Github issue is in status open)

  2. Please run your example Go code with GoSublime. Choose Build With… and run a command:
    go run filename.go

    …no output in real-time. Only after all 10 iterations, when program exits, I see the output. So this plugin is a little buggy?!

  3. The same single-file example code works fine with the official Golang Build from Go developers - with output in real-time. Also, I’ve just found out, that if I add my custom flags to their Run command - not *.go, but all related files one by one - it also forks fine, with output in real-time. So they just do not accept *.go, which is acceptable by a Go compiler. They have a problem with ST3 Cancel Build - it’s disabled even when the process is running, so they have a separated Cancel command, but that’s another story.

0 Likes

#7

I can replicate that result. In my opinion that particular behaviour is definitely being somehow triggered by the GoSublime package, as on my machine the other method provides the “correct” output.

It looks like the package is talking to an external process to execute the code, so perhaps that aspect of it is not being as timely as it could with the output. I don’t know if that’s something that’s configurable on their end or if there is some other go related thing going on, though.

It might be worth pinging the support for the GoSublime package to see if they have anything to say about it, or an explanation as to why it works the way it does.

That might be because if you execute that command from the terminal, the shell expands the *.go into the list of go files in the current directory before it starts the process, so the compiler is not actually seeing *.go at all.

At least that’s how things work in *nix shells (Linux, MacOS, etc). It’s been a long time since I did anything command line related with Windows so I don’t know if they now handle that for you, but back in the murky depths of time it did not and it was a horrible pain in the butt.

0 Likes