Codemountain, Paulo Suzart's Blog

Arquivo da categoria ‘golang

Golang – Templates e formatters

leave a comment »

Adivinhou! Irei escrever: “Quanto tempo sem postar no blog!” É isso mesmo. Quanto tempo!

Se você tem acompanhado meus tweets, deve ter notado que estou focado em Go. Bom, na verdade não estou twittando ou postando no blog sobre Go como fiz com Scala e Clojure por alguns motivos. Mas é proposital.

Não aguentei me segurar e segue uma dica sobre templates em Go. Existem outras soluções, até mesmo mais simples, para o problema. Mas resolvi fazer dessa forma para não interferir nos dados da aplicação por questão de apresentação e visualização de dados.

var CustomFormatter = template.FormatterMap{
    "f2mi": func(w io.Writer, format string, value ...interface{}) {
                 fmt.Fprint(w, strconv.Ftoa64(value[0].(float64)/1000000, 'f', -1))
    },
    "i2mi": func(w io.Writer, format string, value ...interface{}) {
        fmt.Fprintf(w, strconv.Ftoa64(float64(value[0].(int64))/1000000, 'f', -1))
    },
}

var OutPutTemplate = `
=========================================================================
Test Summary (gb. Version: 0.0.2 alpha)
-------------------------------------------------------------------------
Total Go Benchmark Time         | {Elapsed|i2mi} milisecs
Requests Performed              | {TotalSuc}
Requests Lost                   | {TotalErr}
Average Response Time           | {Avg|f2mi} milisecs
Max Response Time               | {Max|i2mi} milisecs
Min Response Time               | {Min|i2mi} milisecs
`
//The resunting summary of a master
type Summary struct {
    Start, End         int64
    TotalSuc, TotalErr int
    Min, Max           int64
    Avg                float64
    Elapsed            int64
}

func (self *Summary) String() string {
    t := template.MustParse(OutPutTemplate, CustomFormatter)
    sw := new(StringWritter)
    t.Execute(sw, self)
    return sw.s
}

Wow! O que está acontecendo aqui? Bem, começando pela variável OutPutTemplate, temos o template usado no GoBenchmark como saída no final do teste.

Note que entre as chaves ({}) estão exatamente os campos da struct Summary, definida mais abaixo. a função (self *Summary) String() em Go, é o correspondente do método .toString() em Java. Ok? Acontece que os campos com in64 estão guardando valores em nanosegundos. Mas para o usuário final desejo mostrar em milisegundos.

E por que não dividir cada campo por 10 elevada à 6 potência? Realmente daria, mas precisaria cuidar disso no meu código da aplicação, e não quero isso.

Uma solução é combinar ao template alguns formatadores de valor. Por isso a média (campo Avg) é representada no template por {Avg|f2mi}, isto é, {Campo|formatador}. Note que em String(), ao efetuar o parse do template eu uso o CustomFormatter para indicar quais os formatadores usados.

É possível usar reflection para, em um mesmo formatador, decidir se o argumento value é um int64 ou float64. Mas, prefiro deixar reflection pra situações realmente relevantes.

É isso! Os formatadores são boas opções e permite soluções criativas.

Se você não me segue no twitter, aproveite: @paulosuzart. Até a próxima!

Written by paulosuzart

julho 1, 2011 at 7:30 am

Publicado em golang

Etiquetado com ,

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.