2
package main

import (
    "bufio"
    "os"
)

func main() {
    bw := bufio.NewWriter(os.Stdin)
    bw2 := bufio.NewWriter(os.Stdout)

    bw.WriteString("Hello, world 1\n")
    bw2.WriteString("Hello, world 2\n")

    bw.Flush()
    bw2.Flush()
}

This code show both string in a local environment. But why does it work differently in different environments?

My local environment OS : macOS 12.6 go : go1.19.2 darwin/amd64 ide : vscode

  • on my local machine :
$ go run myworkspace/main/main.go
Hello, world 1
Hello, world 2
  • on the playground :
# in the 'Output' section
---
Hello, world 2

Program exited.
LeGEC
  • 46,477
  • 5
  • 57
  • 104
limecats
  • 41
  • 3
  • 3
    Hi, a generic remark on StackOverflow guidelines : paste *text* in your question intead of *screen captures* (the output can perfectly be copy pasted) – LeGEC Oct 21 '22 at 06:55

2 Answers2

2

The Go Playground
https://go.dev/play/p/PtoDwCZGggd

Scroll all the way down to "About the Playground"

About the Playground

The Go Playground runs the program inside a sandbox.

There are limitations to the programs that can be run in the playground:

The only communication a playground program has to the outside world is by writing to standard output and standard error.

The Go Playground discards writes to standard input.


Locally, os.Stdin is a file.

var (
    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

Stdin, Stdout, and Stderr are open Files pointing to the standard input, standard output, and standard error file descriptors.

rocka2q
  • 2,473
  • 4
  • 11
2

The bottom line is : your program does not control what thingy will be used as Stdin and Stdout when it is started.

On your local machine, try running : echo "" | go run main.go or go run main.go < anyfile.

(also : you should check for errors in your go code)


It is a standard setup, when running a command from a terminal, that the shell uses the same file descriptor, which points to a read/write terminal, for stdin and stdout/stderr. With that setup, writing to stdin "works".

But you can't rely on it (you shouldn't, actually), and it turns out that the playground doesn't start its processes that way :

package main

import (
    "fmt"
    "os"
)

func main() {
    _, err := os.Stdin.Write([]byte("Hello\n"))
    if err != nil {
        fmt.Fprintln(os.Stderr, "*** error:", err)
    }
}

// Output:
// *** error: write /dev/stdin: bad file descriptor
//
// Program exited.

https://go.dev/play/p/NmxgOsK2ovp


see also :

Why is it possible to write() to STDIN?

Writing to stdin and reading from stdout (UNIX/LINUX/C Programming)

(found by googling "writing to stdin")

LeGEC
  • 46,477
  • 5
  • 57
  • 104