Parse Partial YAML

agolangf · · 463 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m new to Go, coming from many years of Java, Python, this and that. I&#39;m having some fits, without a doubt. </p> <p>My latest head scratcher.... I have a YAML doc with a ton of unrelated config data in it. It&#39;s sort of a bad design, but it&#39;s not changing, so that&#39;s what I&#39;m dealing with.</p> <p>I don&#39;t want to parse the thing as one entity in it&#39;s entirety, but instead just be able to grab bits and pieces out of it based on the task at hand. </p> <p>Given this...</p> <pre><code>--- service: apikey: AIzaSyAxVBj5MkKXl_h7RVhK8wlxQnyK0aD9dHU data: host: &#34;localhost:9666&#34; backup: none password: ~ type GlobalConfig struct { Service struct { Apikey string `yaml:&#34;apikey&#34;` } `yaml:&#34;service&#34;` Data struct { Host string `yaml:&#34;host&#34;` Backup string `yaml:&#34;backup&#34;` Password interface{} `yaml:&#34;password&#34;` } `yaml:&#34;data&#34;` } </code></pre> <p>I&#39;d really like to be able to parse out, for example, just the Data struct and ignore the rest. The idea of dealing with this GlobalConfig struct isn&#39;t appealing. There are ~five dozen unrelated different &#34;things&#34; detailed in the YAML and a huge struct containing all that data give me shivers. This thing has grown organically from many teams and we&#39;re all feeling the pain, though there&#39;s little appetite for a proper design.</p> <p>Any help here? Thanks.</p> <hr/>**评论:**<br/><br/>binaryblade: <pre><p>The (un)marshallers in go generally ignore extra fields in both your go type and the file. So while you need the wrapper struct, you only need the data field.</p></pre>allhatenocattle: <pre><p>In your example where you just want the data field, you could use:</p> <pre><code> type DataConfig struct { Data struct { Host string `yaml:&#34;host&#34;` Backup string `yaml:&#34;backup&#34;` Password interface{} `yaml:&#34;password&#34;` } `yaml:&#34;data&#34;` } </code></pre></pre>allhatenocattle: <pre><p>While I don&#39;t understand your situation well, my inclination would be to parse the config once and the pass the configuration sub-elements to the funcs that need it.</p> <pre><code> type Config struct { ServiceConfig struct { Apikey string `yaml:&#34;apikey&#34;` } `yaml:&#34;service&#34;` DataConfig struct { Host string `yaml:&#34;host&#34;` Backup string `yaml:&#34;backup&#34;` Password interface{} `yaml:&#34;password&#34;` } `yaml:&#34;data&#34;` } config, err := parseConfig() // parse the whole thing, checking for required elements, set defaults, etc if err != nil { log.Fatal(err) } someServiceFunc(config.ServiceConfig) // pass in the part of the config the func requires someDataFunc(config.DataConfig) </code></pre></pre>Redundancy_: <pre><p>It´s possible that the config is a sort of global config for multiple applications where parts are just not relevant to other applications, otherwise I would tend to agree.</p></pre>allhatenocattle: <pre><p>Good point, in which case the first version would probably be appropriate.</p></pre>kooknboo: <pre><p>Thanks to all that have given some tips. This config doc is in fact some type of global config for a whole slew of unrelated apps. The docs changes daily. Fields are added and removed in a willy nilly fashion. It&#39;s a real horror of a design, but that&#39;s the way it is. Battling multiple teams and dozens of developers to try to get this on the road to respectibility isn&#39;t worth it at this point. Especially since we&#39;re hired gone hacking around with Go so they can get a read on whether or not this could be a language of choice for them. Great customer. Odd organization.</p></pre>Emacs24: <pre><p>Take your <code>GlobalConfig</code> structure <a href="https://github.com/go-yaml/yaml" rel="nofollow">and</a></p> <pre><code>var cfg GlobalConfig if err := yaml.Parse(input, &amp;cfg); err != nil { return err } </code></pre></pre>kokster_: <pre><p>Hmmm, I&#39;m trying to understand your use case here. Honestly, If the YAML cannot be changed, and you&#39;re trying to only parse out some specific parts out of the YAML document, and also Unmarshal it into a typed object, then you&#39;d have to write your own parser for the specific types. However, maintaining this can be more of a tech debt than a super big yaml doc. </p> <p>If your concern is performance, efficiency, or speed, then you&#39;d be better off by unmarshaling the whole document, and caching it in a quickly accessible location - either in memory/shared memory or over a network. </p> <p>Then you can choose to retrieve specific subtrees like you wanted. </p> <p>If you&#39;re still looking to just parse out certain parts into typed objects, then like I said, your best bet is to write your own parser for the types you&#39;re working with. If you want to do this in a generic fashion such that this would work with any types, then the algorithm for it would be quite involved.</p> <p>If you already know of an algorithm for such problems, and if you&#39;re just looking for implementation help, I&#39;m sure people here, and myself would be able to show you the way. </p></pre>epiris: <pre><p>What do you mean by &#34;The idea of dealing with this GlobalConfig struct isn&#39;t appealing&#34;? I would make a &#34;config&#34; package to share across Go apps and just write a tiny abstraction for the unappealing parts and cross-team discrepancies. I.e.: <a href="https://play.golang.org/p/xxz6nCc_Vhq" rel="nofollow">play</a>.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

463 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传