conditions - Cambie o si/elseif/else dentro de las plantillas HTML de Golang
golang template conditions (3)
Tengo esta estructura
const (
paragraph_hypothesis = 1<<iota
paragraph_attachment = 1<<iota
paragraph_menu = 1<<iota
)
type Paragraph struct {
Type int // paragraph_hypothesis or paragraph_attachment or paragraph_menu
}
Quiero mostrar mis párrafos de forma dependiente del tipo.
La única solución que encontré estaba basada en funciones dedicadas como isAttachment
probando el Type
en Ir y anidado {{if}}
:
{{range .Paragraphs}}
{{if .IsAttachment}}
-- attachement presentation code --
{{else}}{{if .IsMenu}}
-- menu --
{{else}}
-- default code --
{{end}}{{end}}
{{end}}
De hecho, tengo más tipos, lo que lo hace aún más extraño, saturando tanto el código Go con IsSomething
funciones de IsSomething
como la plantilla con esas {{end}}
.
¿Cuál es la solución limpia? ¿Hay algún switch
o la solución if/elseif/else
en plantillas go? ¿O una forma completamente diferente de manejar estos casos?
Las plantillas no tienen lógica. Se supone que no tienen este tipo de lógica. La lógica máxima que puedes tener es un montón de if
.
En tal caso, se supone que debes hacerlo así:
{{if .IsAttachment}}
-- attachment presentation code --
{{end}}
{{if .IsMenu}}
-- menu --
{{end}}
{{if .IsDefault}}
-- default code --
{{end}}
Puede lograr la funcionalidad de switch
agregando funciones personalizadas a la template.FuncMap .
En el siguiente ejemplo, he definido una función, printPara (paratype int) string
que toma uno de sus tipos de párrafos definidos y cambia su salida en consecuencia.
Tenga en cuenta que, en la plantilla real, el .Paratype
se canaliza a la función printpara
. Así es como pasar parámetros en plantillas. Tenga en cuenta que existen restricciones en el número y la forma de los parámetros de salida para las funciones agregadas a FuncMap
s. Esta página tiene una buena información, así como el primer enlace.
package main
import (
"fmt"
"os"
"html/template"
)
func main() {
const (
paragraph_hypothesis = 1 << iota
paragraph_attachment = 1 << iota
paragraph_menu = 1 << iota
)
const text = "{{.Paratype | printpara}}/n" // A simple test template
type Paragraph struct {
Paratype int
}
var paralist = []*Paragraph{
&Paragraph{paragraph_hypothesis},
&Paragraph{paragraph_attachment},
&Paragraph{paragraph_menu},
}
t := template.New("testparagraphs")
printPara := func(paratype int) string {
text := ""
switch paratype {
case paragraph_hypothesis:
text = "This is a hypothesis/n"
case paragraph_attachment:
text = "This is an attachment/n"
case paragraph_menu:
text = "Menu/n1:/n2:/n3:/n/nPick any option:/n"
}
return text
}
template.Must(t.Funcs(template.FuncMap{"printpara": printPara}).Parse(text))
for _, p := range paralist {
err := t.Execute(os.Stdout, p)
if err != nil {
fmt.Println("executing template:", err)
}
}
}
Produce:
Esta es una hipótesis
Este es un archivo adjunto
Menú
1:
2:
3:Elija cualquier opción:
Espero que eso ayude, estoy bastante seguro de que el código se puede limpiar un poco, pero he tratado de mantenerme cerca del código de ejemplo que proporcionaste.
Sí, puedes usar {{else if .IsMenu}}