Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The efficient way to print a table in GO

Tags:

file

printing

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()) 
like image 523
Fred Avatar asked Mar 19 '16 12:03

Fred


2 Answers

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.

like image 156
17xande Avatar answered Oct 18 '22 05:10

17xande


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)
    }
}
like image 31
peterSO Avatar answered Oct 18 '22 05:10

peterSO