dongtiao2976 2019-07-07 11:31
浏览 260
已采纳

基于变量的Golang格式文本模板

I am trying to use text/template to generate ini-like configurations on the fly, where the original data is provided in yaml format.

I want the resulting output to be different depending on where the request is coming from.

Please consider the following broken code:

package main

import (
    "fmt"
    "gopkg.in/yaml.v3"
    "os"
    "text/template"
)

var yamlData = `
# comment
---
States:
- StateName: California
  DateEstablished: September 9, 1850
  Cities:
  - CityName: Los Angeles
    Population: 4 Million
  - CityName: Santa Barbara
    Population: 92 Thousand
  - CityName: San Jose
    Population: 1 Million
- StateName: Washington
  DateEstablished: November 11, 1889
  Cities:
  - CityName: Seattle
    Population: 724 Thousand
    Climate: wet
  - CityName: Spokane
    Population: 217 Thousand
    Climate: dry
  - CityName: Scappoose
    Population: 7
`

const reportTemplate string = `{{ range . }}
# {{ if .CityName == requestingCityName }}
# {{ .CityName }}
[RequestingCity]
Population = {{ .Population }}
{{ if .Climate }}Climate = {{ .Climate }}{{ end }}
{{ end }}
# {{ if .CityName != requestingCityName }}
# {{ .CityName }}
[City]
Population = {{ .Population }}
{{ if .Climate }}Climate = {{ .Climate }}{{ end }}
{{ end }}
{{ end }}
`

type dataStruct struct {
    States []struct {
        StateName       string `yaml:"StateName"`
        DateEstablished string `yaml:"DateEstablished"`
        Cities          []struct {
            CityName   string `yaml:"CityName"`
            Population string `yaml:"Population"`
            Climate    string `yaml:"Climate,omitempty"`
        } `yaml:"Cities"`
    } `yaml:"States"`
}

func (d *dataStruct) readData(data []byte) *dataStruct {
    yaml.Unmarshal(data, d)
    return d
}

func main() {

    var report dataStruct
    report.readData([]byte(yamlData))
    t := template.Must(template.New("new").Parse(reportTemplate))

    requestingStateName := "Washington"
    requestingCityName := "Seattle"

    for i := range report.States {
        if report.States[i].StateName == requestingStateName {
            x := report.States[i].Cities
            fmt.Println(t.Execute(os.Stdout, x))

        }
    }
}

Most of this code "works" the way i would expect it to, but the part i am having problems with is how to make the template.

I want to be able to change the value for requestingCityName so that the output will change like so:

if requestingCityName == "Scappoose" then the output would be like so:


# Scappoose
[RequestingCity]
Population = 7

# Spokane
[City]
Population = 217 Thousand
Climate = dry

# Seattle
[City]
Population = 724 Thousand
Climate = wet

or if requestingCityName == "Seattle" then the output would be like so:


# Seattle
[RequestingCity]
Population = 724 Thousand
Climate = wet

# Spokane
[City]
Population = 217 Thousand
Climate = dry

# Scappoose
[City]
Population = 7

How would make the template so that I can achieve the desired behaviour?

  • 写回答

2条回答 默认 最新

  • duangou2028 2019-07-07 13:00
    关注

    One simple solution would be to pass a different data object to Template.Execute. Something like:

    type templateData struct {
        requestingCityName string
        cities             []citiesStruct // or whatever you name the struct
    }
    ...
    fmt.Println(t.Execute(os.Stdout, templateData{requestingCityName, x}))
    

    This solution would require you to update your template to work with the new context struct (i.e. that the old cities array is now .cities rather than .), but it gives you access to .requestingCityName.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?