63

Is there something like Ruby's awesome_print in Go?

For example in Ruby you could write:

require 'ap'
x = {a:1,b:2} // also works for class
ap x

the output would be:

{ 
  "a" => 1,
  "b" => 2
}

closest thing that I could found is Printf("%#v", x)

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Kokizzu
  • 24,974
  • 37
  • 137
  • 233

5 Answers5

123

If your goal is to avoid importing a third-party package, your other option is to use json.MarshalIndent:

x := map[string]interface{}{"a": 1, "b": 2}
b, err := json.MarshalIndent(x, "", "  ")
if err != nil {
    fmt.Println("error:", err)
}
fmt.Print(string(b))

Output:

{
    "a": 1,
    "b": 2
}

Working sample: http://play.golang.org/p/SNdn7DsBjy

Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
  • 1
    Testing multiple levels of indention. https://play.golang.org/p/d3nO4Rht90 – Xeoncross Dec 19 '16 at 15:23
  • 1
    Marshal gets intro trouble when there is a custom struct (unsupported type error). Any easy way to fix that? – etang Aug 09 '17 at 00:18
  • @etang You would have to show a simple example for me to give you a better answer (perhaps in the Playground?). I imagine you'll have to implement one of the JSON package interfaces for unmarshalling your type if it becomes complex. – Simon Whitehead Aug 09 '17 at 00:40
27

Nevermind, I found one: https://github.com/davecgh/go-spew

// import "github.com/davecgh/go-spew/spew"
x := map[string]interface{}{"a":1,"b":2}
spew.Dump(x)

Would give an output:

(map[string]interface {}) (len=2) {
 (string) (len=1) "a": (int) 1,
 (string) (len=1) "b": (int) 2
}
Kokizzu
  • 24,974
  • 37
  • 137
  • 233
14

If you want pretty coloured output, you can use pp.

https://github.com/k0kubun/pp

import "github.com/k0kubun/pp"
...
pp.Print(m)

pp preview

Ruben S
  • 931
  • 1
  • 10
  • 11
4

I just wrote a simple function based on Simons answer:

func dump(data interface{}){
    b,_:=json.MarshalIndent(data, "", "  ")
    fmt.Print(string(b))
}
MSS
  • 3,520
  • 24
  • 29
3

I came up to use snippet like this:

func printMap(m map[string]string) {
    var maxLenKey int
    for k, _ := range m {
        if len(k) > maxLenKey {
            maxLenKey = len(k)
        }
    }

    for k, v := range m {
        fmt.Println(k + ": " + strings.Repeat(" ", maxLenKey - len(k)) + v)
    }
}

The output will be like this:

short_key:       value1
really_long_key: value2

Tell me, if there's some simpler way to do the same alignment.

andstepko
  • 111
  • 1
  • 4
  • 5
    You can use `fmt.Printf("%*s: %s", maxLenKey, k, v)` to avoid the `strings.Repeat` call and all that concatenation. – Eric Lindsey Nov 11 '18 at 08:24