在Go模板中随机选择内容

时间:2014-10-06 11:29:53

标签: templates go

我想根据给定的权重随机选择生成文档的一部分,类似于这个伪代码:

{{prob 50}}
    This will appear with probability 50%.
{{prob 30}}
    This will appear with probability 30%.
{{prob 20}}
     You got the idea.
{{endprob}}

到目前为止,我想到的最好的事情是:

{{choose . "template1" 50 "template2" 30 "template3" 20}}

其中choose是属于FuncMap的函数。当前模板作为例如传递给它自己。 .TtemplateN是关联的模板。该函数将选择模板,在.T中查找并使用.进行渲染。另一个类似的选择是直接将templateN作为.的一部分传递。

我想知道是否有更优雅/更少的hackish方式?我想,在text/template中无法创建自定义操作,是吗?

1 个答案:

答案 0 :(得分:3)

标准模板包不支持自定义操作。

您可以使用功能映射和内置{{prob}}/{{endprob}}操作来接近建议的{{if}}操作。

将权重转换为[0.0,1.0]中的非重叠范围。使用[0.0,1.0]中的随机数在模板中使用if动作选择替代方案。

var t = template.Must(template.New("").
    Funcs(template.FuncMap{"rand": rand.Float64}).
    Parse(`
{{$r := rand}}
{{if le $r 0.5}}
    This will appear with probability 50%.
{{else if le $r 0.8}}
    This will appear with probability 30%.
{{else}}
     You got the idea.
{{end}}`))

playground

这是一个替代方案,允许您在模板中指定权重而不是范围:

type randPicker struct {
    n float64 // random number in  [0.0,1.0)
    t float64 // total of weights so far
}

func (rp *randPicker) Weight(w float64) bool {
    rp.t += w
    return rp.t <= rp.n
}

func newRandPicker() *randPicker {
    return &randPicker{n: rand.Float64()}
}

var t = template.Must(template.New("").
    Funcs(template.FuncMap{"rp": newRandPicker}).
    Parse(`
{{$rp := rp}}
{{if rp.Weight 0.50}}
    This will appear with probability 50%.
{{else if rp.Weight 0.30}}
    This will appear with probability 30%.
{{else}}
    You got the idea
{{end}}`))

playground