英文:
golang text/template startswith function
问题
我在Go的text/template
包中没有看到任何类型的startswith
函数。这是最好的实现吗?
{{if eq (slice $c 0 5) "begin"}}
英文:
I don't see any type of startswith
function in the Go text/template
package. Is this the best implementation?
{{if eq (slice $c 0 5) "begin"}}
答案1
得分: 4
没有内置的startswith
模板函数。
最干净的方法是注册一个具有该功能的自定义函数:
func main() {
t := template.Must(template.New("").Funcs(template.FuncMap{
"hasPrefix": strings.HasPrefix,
}).Parse(src))
for _, s := range []string{"foo", "begining"} {
if err := t.Execute(os.Stdout, s); err != nil {
panic(err)
}
}
}
const src = `{{.}}: {{if hasPrefix . "begin"}}yes{{else}}no{{end}}
`
这将输出(在Go Playground上尝试):
foo: no
begining: yes
如果您不能或不想注册自定义函数,slice
可以用于字符串,但必须小心使用:如果输入字符串的长度小于5个字节,您将得到一个模板执行错误!
相反(如果您不想注册自定义函数),我建议使用内置的printf
函数,其中_精度_是要比较的字符串的长度。如果输入字符串较短,printf
不会引发错误:
{{if eq (printf "%.5s" .) "begin"}}yes{{else}}no{{end}}
这将输出相同的结果。在Go Playground上尝试这个。
请注意,使用hasPrefix
更安全、更清晰和更简单,因为我们不需要硬编码前缀的长度(5
)。
请注意,使用显式参数索引,我们还可以使此部分动态化:
{{$prefix := "begin"}}{{if eq (printf "%.[1]*s" (len $prefix) .) $prefix}}yes{{else}}no{{end}}
正如您所看到的,我们可以摆脱前缀的硬编码长度5
。这同样输出相同的结果,在Go Playground上尝试一下。
最后要注意的一点是,对字符串进行切片时,索引被解释为_字节索引_,而格式字符串中使用的精度被解释为_符文计数_!
英文:
There is no builtin startswith
template function.
The cleanest is if you register a custom function with that functionality:
func main() {
t := template.Must(template.New("").Funcs(template.FuncMap{
"hasPrefix": strings.HasPrefix,
}).Parse(src))
for _, s := range []string{"foo", "begining"} {
if err := t.Execute(os.Stdout, s); err != nil {
panic(err)
}
}
}
const src = `{{.}}: {{if hasPrefix . "begin"}}yes{{else}}no{{end}}
`
This will output (try it on the Go Playground):
foo: no
begining: yes
If you can't or don't want to register a custom function, slice
works for strings, but you must use it with care: if the input string is shorter than 5 bytes, you'll get a template execution error!
Instead (if you don't want to register a custom function), I suggest to use the builtin printf
function with precision being the length of the string to compare to. printf
will not panic if the input string is shorter:
{{if eq (printf "%.5s" .) "begin"}}yes{{else}}no{{end}}
This outputs the same. Try this one on the Go Playground.
Note that using hasPrefix
is safer, cleaner and simpler as we don't have to hard-code the length of the prefix (5
).
Note that using explicit argument indices we can also make this part dynamic:
{{$prefix := "begin"}}{{if eq (printf "%.[1]*s" (len $prefix) .) $prefix}}yes{{else}}no{{end}}
As you can see, we could get rid of the hard-coded length of 5
of the prefix. This again outputs the same, try it on the Go Playground.
One last thing to note: slicing a string interprets indices as byte-indices, while the precision used in a format string is interpreted as rune count!
答案2
得分: 0
我认为你是对的。Go的text/template包没有提供内置的startswith
函数。要在Go的text/template中检查字符串是否以特定前缀开头,你不能直接使用(slice $c 0 5)
结合eq
,因为slice
函数返回的是一个新的切片,而不是一个字符串。
也许一个使用自定义函数的示例可以是这样的:
package main
import (
"os"
"strings"
"text/template"
)
func StartsWithPrefix(str, prefix string) bool {
return strings.HasPrefix(str, prefix)
}
func main() {
tmpl := template.Must(template.New("").Funcs(template.FuncMap{
"startswith": StartsWithPrefix,
}).Parse(`{{if startswith .C "begin"}}(Chester's Bennington voice)It starts with "One Thing"{{end}}`))
data := struct {
C string
}{
C: "beginning bla bla",
}
err := tmpl.Execute(os.Stdout, data)
if err != nil {
panic(err)
}
}
在这个示例中,我们定义了StartsWithPrefix函数,将其注册为startswith使用template.FuncMap,然后在模板中使用{{if startswith $c "begin"}}来检查$c的值是否以前缀"begin"开头。如果是,将打印出消息"(Chester's Bennington voice)It starts with 'One Thing'"。
你也可以在Go Playground中检查它 https://go.dev/play/p/hEvhYo_iHhM
英文:
I think that you are right. Go text/template package does not provide a built-in startswith
function. To check if a string starts with a specific prefix in Go text/templates, you cannot directly use (slice $c 0 5)
in combination with eq
because the slice
function returns a new slice, not a string.
Maybe an example of how to use a custom function would be like:
package main
import (
"os"
"strings"
"text/template"
)
func StartsWithPrefix(str, prefix string) bool {
return strings.HasPrefix(str, prefix)
}
func main() {
tmpl := template.Must(template.New("").Funcs(template.FuncMap{
"startswith": StartsWithPrefix,
}).Parse(`{{if startswith .C "begin"}}(Chester's Bennington voice)It starts with "One Thing"{{end}}`))
data := struct {
C string
}{
C: "beginning bla bla",
}
err := tmpl.Execute(os.Stdout, data)
if err != nil {
panic(err)
}
}
In this example, we define the StartsWithPrefix function, register it as startswith using template.FuncMap, and then use {{if startswith $c "begin"}} in the template to check if the value of $c starts with the prefix "begin". If it does, the message "(Chester's Bennington voice)It starts with 'One Thing'" will be printed.
You can also check it in Go playground https://go.dev/play/p/hEvhYo_iHhM
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论