Как проверить, является ли значение строкой в ​​шаблоне

Я хотел бы узнать, возможно ли это, и если да, то как проверить, является ли значение строкой в ​​​​шаблоне Go.

Я пробовал следующее без успеха

{{- range .Table.PrimaryKeys.DBNames.Sorted }}{{ with (index $colsByName .)}}
{{ .Name }}: {{ if .IsArray }}[]{{ end }}'{{.Type}}', {{end}}
{{- end }}
{{- range $nonPKDBNames }}{{ with (index $colsByName .) }}
    {{ .Name }}: {{ if .IsArray }}[]{{end -}} {
  type: {{ if .Type IsString}}GraphQLString{{end -}}, # line of interest where Type is a value that could be a number, string or an array
}, {{end}}
{{- end }}

И это ошибка, которую я получаю

Ошибка: ошибка синтаксического анализа TablePaths: ошибка синтаксического анализа содержимого шаблон: шаблон: templates/table.gotmpl:42: функция "IsString" не определена


person Siya    schedule 11.05.2019    source источник
comment
Что .Type вы хотите протестировать? Покажите минимально воспроизводимый пример.   -  person icza    schedule 11.05.2019
comment
Это не важно, потому что Type в этом примере — просто значение.   -  person Siya    schedule 11.05.2019
comment
Это важно, потому что, судя по его названию, похоже, что вы храните тип как что-то вроде reflect.Type, что изменит способ достижения того, что вы хотите.   -  person icza    schedule 11.05.2019


Ответы (1)


С пользовательской функцией

В шаблонах нет предварительно объявленной функции IsString(), но мы можем легко зарегистрировать и использовать такую ​​функцию:

t := template.Must(template.New("").Funcs(template.FuncMap{
    "IsString": func(i interface{}) bool {
        _, ok := i.(string)
        return ok
    },
}).Parse(`{{.}} {{if IsString .}}is a string{{else}}is not a string{{end}}`))
fmt.Println(t.Execute(os.Stdout, "hi"))
fmt.Println(t.Execute(os.Stdout, 23))

Это выведет (попробуйте на Go Playground):

hi is a string<nil>
23 is not a string<nil>

(Литералы <nil> в конце строк — это значения ошибок, возвращаемые выполнением шаблона, говорящие об отсутствии ошибок.)

Использование глаголов printf и %T

Мы также можем сделать это без пользовательских функций. По умолчанию доступна функция printf, которая является псевдонимом для < a href="https://golang.org/pkg/fmt/#Sprintf" rel="nofollow noreferrer">fmt.Sprintf(). И есть глагол %T, который выводит тип аргумента.

Идея состоит в том, чтобы вызвать printf %T для значения и сравнить результат с "string", и все готово:

t := template.Must(template.New("").
    Parse(`{{.}} {{if eq "string" (printf "%T" .)}}is a string{{else}}is not a string{{end}}`))
fmt.Println(t.Execute(os.Stdout, "hi"))
fmt.Println(t.Execute(os.Stdout, 23))

Это также выведет (попробуйте на Go Playground):

hi is a string<nil>
23 is not a string<nil>
person icza    schedule 11.05.2019
comment
Где прописать эту функцию? Я пишу шаблон перехода, который передаю в этот пакет gnorm.org. Так что мне не очень понятно, куда мне добавить этот код, чтобы я мог использовать его в шаблоне, на который я ссылался выше. - person Siya; 12.05.2019
comment
@brandNew Пользовательские функции должны быть зарегистрированы до синтаксического анализа текста шаблона, поскольку обработчик шаблонов должен иметь возможность статически анализировать шаблон и заранее знать, какие литералы обозначают допустимые пользовательские функции. Если у вас нет доступа к шаблону для этого, используйте второй подход (с функцией printf), который не требует регистрации пользовательских функций. Подробнее см. в разделе Использование пользовательской функции в шаблоне условия Go. - person icza; 12.05.2019