Stuck with interface{} + map/slice + pointer

agolangf · · 653 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>So the core idea here is that I want to Unmarshal some JSON and then, given an address within the returned interface{}, retrieve or modify an item at that address. Of course, if someone can point me to something that does this, that&#39;d be great.</p> <p>I&#39;ve got the stuff to retrieve a given item at an address together and it works - <a href="http://play.golang.org/p/e_eoZpj_L2" rel="nofollow">http://play.golang.org/p/e_eoZpj_L2</a>. IDK that it&#39;s solid or the best thing out there (I&#39;m sure it&#39;s not) but it works, and I understand it (even if it does make a ton of allocations).</p> <p>I however cannot get the stuff to modify an item working - my current code (that is wrong) is:</p> <pre><code>func SetItem(data *interface{}, target []interface{}, value interface{}) error { if targetInt, ok := target[0].(int); ok { if dataSafe, ok := data.(*[]interface{}); ok { // do stuff to assign for slice } } else if targetString, ok := target[0].(string); ok { if dataSafe, ok := data.(*map[string]interface{}); !ok { // do stuff to assign for map } } else { return fmt.Errorf(&#34;bad address - %s&#34;, target) } } func main() { testBytes := []byte(`{&#34;Everything&#34;:&#34;Awesome&#34;,&#34;Team&#34;:{&#34;Everything&#34;:&#34;Cool&#34;}}`) var testData interface{} err := json.Unmarshal(testBytes, &amp;testData) err = SetItem(&amp;testData, []interface{}{&#34;Team&#34;, &#34;Everything&#34;}, interface{}(&#34;Not Cool&#34;)) fmt.Println(testData) } </code></pre> <p>When I run this though I keep getting errors around the same thing - <a href="http://play.golang.org/p/S3mRPg148k" rel="nofollow">http://play.golang.org/p/S3mRPg148k</a></p> <pre><code>prog.go:11: invalid type assertion: data.(*[]&lt;inter&gt;) (non-interface type *interface {} on left) prog.go:29: invalid type assertion: data.(*map[string]&lt;inter&gt;) (non-interface type *interface {} on left) </code></pre> <p>You must not be able to type assert to a pointer type? Is that correct? Is there a better way to do this while avoiding diving deep into <code>reflect</code>? All in all, I&#39;m stuck, I don&#39;t get this, and I wanted to reach out before I got frustrated.</p> <p><strong>ANY</strong> help is appreciated :-)</p> <hr/>**评论:**<br/><br/>alexisnotonfire: <pre><p>General note, you almost never want *interface{}, but instead expect interface{} and assert (*sometype)</p> <p>edit: but i think the bigger question is why are you so keen on using interface? perhaps if you were to try something like <a href="https://mholt.github.io/json-to-go/" rel="nofollow">https://mholt.github.io/json-to-go/</a> to create a struct, your code will be far simpler.</p></pre>jahayhurst: <pre><p>The reality is that I probably don&#39;t want a *interface{}, but I want to be able to modify the interface, so I figured I wanted to pass a pointer to the interface.</p> <p>Still, someone else posted an alternate example that works - so I&#39;ll work backwards from that :-)</p></pre>GopherFromHell: <pre><p>take a look here <a href="https://play.golang.org/p/lezghED5N1" rel="nofollow">https://play.golang.org/p/lezghED5N1</a></p></pre>jahayhurst: <pre><p>Thank you so much! :-) I don&#39;t know off hand <em>why</em> it works, but I&#39;m so deep in the tank now that having something that does work is enough - I can work backwards from there (and will happily do so).</p> <p>I have some learning to do, and it looks like I&#39;m going to be digging through more documentation to earn that learning, but I&#39;m ok with doing that. I have a thread to get started with here.</p> <p>Once again, TY for the help :-) If I only had more upvotes to give...</p> <p>As a side note: someone downvoted this post. ....Why? Is there something wrong with this? (Other than this generally being very bad idea, or at least a really really shady idea?)</p></pre>GopherFromHell: <pre><p>with some comments and some print statements: <a href="https://play.golang.org/p/c89_CGGFcv" rel="nofollow">https://play.golang.org/p/c89_CGGFcv</a></p> <p>Usually when parsing JSON the structure (or at least part) is know beforehand, parsing to a struct is much nicer: <a href="https://play.golang.org/p/tmM0x4Ygoy" rel="nofollow">https://play.golang.org/p/tmM0x4Ygoy</a></p> <p>Of course by your description i assume that it&#39;s a more generic case than that</p></pre>natefinch: <pre><p>What are you trying to accomplish? You&#39;re asking about why your solution doesn&#39;t work, but we don&#39;t know what the problem is. </p> <p>This is probably not the right way to be handling JSON. I&#39;m sure there&#39;s a better way. </p> <p>Explain the problem from the beginning, and then we can probably better help you.</p></pre>jahayhurst: <pre><p>Let me try explaining again:</p> <p>I&#39;m trying to unmarshal any valid json input into a generic interface{} and then modify a value within it at a given location <em>within that interface [edit]</em> (if that location is valid).</p> <p>In a more broad sense:</p> <p>I&#39;m trying to build a binary like curl that will take JSON as input, will send it to a given address, then output the response. However, the API I am working against uses paginated responses - so I want to increment a value at a location within the input until one value in the output is greater than/equal to another - basically work my way through every page of the response.</p> <p>However, once I get this working, I&#39;ll in turn probably use this in at least one other place - pluck values from JSON input and throw them to standard output - and possibly more than that.</p></pre>freeformz: <pre><p>It&#39;s probably easier to make a struct the represents the pagination part of the response (to capture the offset / total / length / whatever) and just let JSON unmarshall that. You can use something like a TeeReader (or other golang constructs) to capture a copy of the data for other processing / output.</p></pre>

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

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