Fred
Fred

Reputation: 697

The efficient way to print a table in GO

I would like to know a simple and efficient way to print a table in Go. The solution I found works but it is really ugly.

many Thanks !

outfile := "file.tsv"
f, err := os.Create(outfile)
var buffer bytes.Buffer

buffer.WriteString(a[i])
buffer.WriteString("\t")
buffer.WriteString(a[j])
buffer.WriteString("\t")
buffer.WriteString(strconv.FormatFloat(x, 'f', 4, 64))
buffer.WriteString("\n")
// // write results to outfile
f.WriteString(buffer.String()) 

Upvotes: 26

Views: 30531

Answers (3)

HobbyMarks
HobbyMarks

Reputation: 366

choose a exist package can simple your code and also increase code maintainability。try go-pretty

+---------------------------------------------------------------------+
| Game of Thrones                                                     +
+-----+------------+-----------+--------+-----------------------------+
|   # | FIRST NAME | LAST NAME | SALARY |                             |
+-----+------------+-----------+--------+-----------------------------+
|   1 | Arya       | Stark     |   3000 |                             |
|  20 | Jon        | Snow      |   2000 | You know nothing, Jon Snow! |
| 300 | Tyrion     | Lannister |   5000 |                             |
+-----+------------+-----------+--------+-----------------------------+
|     |            | TOTAL     |  10000 |                             |
+-----+------------+-----------+--------+-----------------------------+

Upvotes: 2

17xande
17xande

Reputation: 2813

The tabwriter package in the standard library is simple and easy for this kind of thing:

w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
fmt.Fprintln(w, "a\tb\tc\td\t")
fmt.Fprintln(w, "aa\tbb\tcc\t")
fmt.Fprintln(w, "aaa\tbbb\tccc\t")
fmt.Fprintln(w, "aaaa\tbbbb\tcccc\tdddd\t")
w.Flush()

// Prints out:
// a    b    c    d 
// aa   bb   cc   
// aaa  bbb  ccc  
// aaaa bbbb cccc dddd 

You can replace the os.Stdout with any io.Writer.

Upvotes: 53

peterSO
peterSO

Reputation: 166714

For example,

package main

import (
    "encoding/csv"
    "fmt"
    "os"
    "strconv"
)

func main() {
    outfile := "file.tsv"
    f, err := os.Create(outfile)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    defer f.Close()
    w := csv.NewWriter(f)
    defer w.Flush()
    w.Comma = '\t'

    a := []string{"a", "b"}
    i, j := 0, 1
    x := float64(2.7)

    // Write row.
    err = w.Write(
        []string{
            a[i], a[j],
            strconv.FormatFloat(x, 'f', 4, 64),
        },
    )
    if err != nil {
        fmt.Println(err)
    }
}

Output:

$ cat file.tsv
a   b   2.7000
$

If you use goroutines, here's a version that uses a mutex to protect the csv.Writer.

package main

import (
    "encoding/csv"
    "fmt"
    "os"
    "strconv"
    "sync"
)

type csvWriter struct {
    w *csv.Writer
    m sync.Mutex
}

func (c *csvWriter) write(rec []string) error {
    c.m.Lock()
    defer c.m.Unlock()
    return c.w.Write(rec)
}

func (c *csvWriter) flush() {
    c.m.Lock()
    defer c.m.Unlock()
    c.w.Flush()
}

func main() {
    outfile := "file.tsv"
    f, err := os.Create(outfile)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    defer f.Close()
    w := csvWriter{w: csv.NewWriter(f)}
    defer w.flush()
    w.w.Comma = '\t'

    a := []string{"a", "b"}
    i, j := 0, 1
    x := float64(2.7)

    // Write row.
    err = w.write(
        []string{
            a[i], a[j],
            strconv.FormatFloat(x, 'f', 4, 64),
        },
    )
    if err != nil {
        fmt.Println(err)
    }
}

Upvotes: 4

Related Questions