How can I print to Stderr in Go without using log

84,010

Solution 1

The Go builtin functions print and println print to stderr. So if you simply want to output some text to stderr you can do

package main

func main() {
    println("Hello stderr!")
}

Documentation: https://golang.org/pkg/builtin/#print

Solution 2

If you don't want timestamps, just create a new log.Logger with flag set to 0:

l := log.New(os.Stderr, "", 0)
l.Println("log msg")

EDIT:

Is the following good Go?

os.Stderr.WriteString("Message")

This is acceptable, and you can also use fmt.Fprintf and friends to get formatted output:

fmt.Fprintf(os.Stderr, "number of foo: %d", nFoo)

Solution 3

Using the fmt package, you can choose to write to stderr this way:

import "fmt"
import "os"

func main() {
    fmt.Fprintln(os.Stderr, "hello world")
}

Solution 4

os.Stderr is an io.Writer, so you can use it in any function which accepts an io.Writer. Here are a few examples:

str := "Message"
fmt.Fprintln(os.Stderr, str)
io.WriteString(os.Stderr, str)
io.Copy(os.Stderr, bytes.NewBufferString(str))
os.Stderr.Write([]byte(str))

It all depends on how exactly you have the string you want to print (i.e. if you want to format it first, if you have it as an io.Reader, if you have it as a byte slice...). And there can be a lot more ways.

Solution 5

By default the logger flags are set to Ldate | Ltime. You can change the logger format to any of the following (from the golang log documentation):

Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
Ltime                         // the time in the local time zone: 01:23:23
Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
Llongfile                     // full file name and line number: /a/b/c/d.go:23
Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
LstdFlags     = Ldate | Ltime // initial values for the standard logger

For example, flags Ldate | Ltime (or LstdFlags) produce,

2009/01/23 01:23:23 message

While flags Ldate | Ltime | Lmicroseconds | Llongfile produce,

2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message

You can also set the default logger to not print anything by setting the flag to 0:

log.SetFlags(0)
Share:
84,010
Max Heiber
Author by

Max Heiber

Updated on August 18, 2020

Comments

  • Max Heiber
    Max Heiber over 3 years

    How can I write a message to Stderr without using log?

    A comment in this SO post shows how to do it with log: log.Println("Message"), but what if I don't want a timestamp?

    Is the following good Go?

    os.Stderr.WriteString("Message")

  • Ainar-G
    Ainar-G about 9 years
    If you're going to use stderr to actually log things, use a logger. Otherwise, a simple os.Stderr.WriteString will suffice, IMO.
  • Andrioid
    Andrioid over 5 years
    Best answer. Although, my personal preference is using fmt.Fprintf or fmt.Fprintln. If you're doing this many places in your program, maybe wrap it in a function then you can easily change stderr to stdout or whatever writer you want.
  • Daniel Gray
    Daniel Gray over 3 years
    Good tip! However, it says: "Print is useful for bootstrapping and debugging; it is not guaranteed to stay in the language." so maybe not for long-term projects?
  • weakish
    weakish over 3 years
    IMO, print and println are used for debugging.
  • KEINOS
    KEINOS almost 3 years
    Indeed the documents say that println prints to STDERR. Though, it seems not printing to STDERR by default. Throwing away the STDERR by go run ./main.go 2>/dev/null 3>/dev/null, I'm still getting a "Hello stderr!" message. Which means that it's printing to STDOUT. I think @julienc answer fmt.Fprintln(os.Stderr, "Hello stderr!") should be the accepted answer too.
  • Sridhar Sarnobat
    Sridhar Sarnobat almost 3 years
    Note to self: be careful about using | grep 'DEBUG' in combination with 2>. Somehow I still get the stderr output on my terminal while using 2>.
  • Speeddymon
    Speeddymon almost 3 years
    @SridharSarnobat each command in a group of piped command can independently output to stderr. Consider this instead: somecommand 2>/dev/null |grep 'DEBUG' 2>/dev/null in order to send grep errors to /dev/null in addition to somecommand errors
  • taras
    taras over 2 years
    @KEINOS what OS do you use to get println in stdout? I am trying to reproduce to understand it better, however it still prints into stderr
  • KEINOS
    KEINOS over 2 years
    @TarasMatsyk My bad! I DO GET the STDERR with println. I think I was confused. The reason was that I ran the code on the Docker container. docker run --rm -it -v "$(pwd)":/root/src golang:alpine go run /root/src/main.go 2>/dev/null. This will print the error message since the container prints to STDOUT the "outputs inside the container".
  • user5359531
    user5359531 almost 2 years
    how are you supposed to use these flags?