2017-02-13 12 views
3

В моем ходе код я часто использую if как этотшаблона Go и функции

if user && user.Registered { } 

эквивалентного код в их шаблонах будут

{{ if and .User .User.Registered }} {{ end }} 

К сожалению кодам в шаблоне не удается, если .User является nil:/

Можно ли добиться того же в шаблонах go?

ответ

5

Шаблон and функция не делает short circuit оценка как Go && оператор.

Аргументы функции and оцениваются перед вызовом функции. Выражение .User.Registered всегда оценивается, даже если .User равно нулю.

Исправление заключается в использовании вложенных if:

{{if .User}}{{if .UserRegistered}} {{end}}{{end}} 

Вы можете избежать вложенной if или with с помощью функции шаблона:

func isRegistered(u *user) bool { 
    return u != nil && u.Registered 
} 

const tmpl = `{{if isRegistered .User}}registered{{else}}not registered{{end}}` 

t := template.Must(template.New("").Funcs(template.FuncMap{"isRegistered": isRegistered}).Parse(tmpl)) 

playground example

+0

Я пытаюсь escape, используя вложенный ifs .. потому что он будет дублировать слишком много кода шаблона между – Goranek

+0

, хотя это это не настоящее решение, я собираюсь принять его. – Goranek

2

Другой вариант заключается в использовании действие {{with}} вместо функции шаблона and.

Цитирование из пакета РОУ text/template:

{{with pipeline}} T1 {{end}} 
    If the value of the pipeline is empty, no output is generated; 
    otherwise, dot is set to the value of the pipeline and T1 is 
    executed. 

Использование {{with}} часто приводит к более чистой и более короткий код, так как внутри {{with}} точка . уже установлен в непустой «обертке» , .User в нашем случае; кроме того, вам не нужно беспокоиться о том, как и если оцениваются аргументы функции шаблона and.

Шаблон переписан:

{{with .User -}} 
    {{if .Registered}}REGISTERED{{end}} 
{{- end}} 

Тестирование без и с пользователем:

t := template.Must(template.New("").Parse(tmpl)) 

fmt.Println("No user:") 
if err := t.Execute(os.Stdout, nil); err != nil { 
    panic(err) 
} 

u := struct{ Registered bool }{true} 
fmt.Printf("User: %+v\n", u) 
if err := t.Execute(os.Stdout, map[string]interface{}{"User": u}); err != nil { 
    panic(err) 
} 

Output (попробуйте его на Go Playground):

No user: 
User: {Registered:true} 
REGISTERED 
+0

К сожалению, это то же самое, что и вложенные ifs, которые я пытаюсь использовать – Goranek

+0

@Goranek. Вы не упомянули об этом в своем вопросе. – icza

+0

жаль, что я думал, что было очевидно, чего я хотел достичь :( – Goranek