Go strings question. Thanks!

polaris · · 641 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Please let me know if it&#39;s taboo to ask questions here; I&#39;ve seen other people do it, but I agree it&#39;s nicer to have more articles than &#34;I can&#39;t get X to work.&#34; Especially questions like this...</p> <p>When I have my own types (or other people&#39;s types) in code, and require a string version of them, is it idiomatic to use the fmt.Sprint function? Is there a better way to convert to a string? Simply using the regular string conversion function won&#39;t work, since I usually want to convert a custom type.</p> <p>If you have time, could you explain what the Sprint function is doing? Just essentially printing its content into a string?</p> <p>Thanks so much! I feel like I&#39;m starting to get a hold of everything, and have made some complicated programs, but sometimes feel like I am doing things in really roundabout ways.</p> <p>Thanks! </p> <hr/>**评论:**<br/><br/>DeedleFake: <pre><p>Some types supply a String() method in order to satisfy fmt.Stringer, but many types don&#39;t. The ability to display themselves as readable text isn&#39;t something that most types have any need to do, after all. Having said that, using fmt.Sprint and its variants is a pretty good way to format arbitrary types as strings.</p> <p>If you&#39;re trying to convert to a string in order to write data to, for example, a TCP stream, remember that fmt.Fprint takes an io.Writer, which is satisfied by a large number of stream-like types. For example:</p> <pre><code>var buf bytes.Buffer fmt.Fprintf(&amp;buf, &#34;%q&#34;, &#34;This text gets quoted and appended to the buffer.&#34;) </code></pre></pre>plasticmacaroni: <pre><p>This is exactly what I&#39;m looking for! And interesting note about writing data or using streams. I&#39;ll try to remember that instead of something dumb like converting to a string and then converting again to something write-ready.</p> <p>Thank you!</p></pre>izuriel: <pre><p>I can’t speak for it’s “taboo-ness” but this is the approach I take when stringifying values as well and it’s worked fine for all the projects I’ve used it in thus far.</p></pre>tkreadit: <pre><p>Is this what you are looking for?</p> <p><a href="http://play.golang.org/p/6n0qA5WsaO">http://play.golang.org/p/6n0qA5WsaO</a></p> <p>Take a look at fmt.Stringer and fmt.GoStringer interfaces.</p></pre>plasticmacaroni: <pre><p>This is actually really helpful to see these functions in use, but not every type actually implements Stringer() or GoStringer() from what I can tell, so sometimes I have to look for another way.</p> <p>Thank you!</p></pre>ejayben: <pre><p>I&#39;m pretty sure you are free to write extension methods for any struct (or am I wrong?).</p> <pre><code>func (*MyArbitraryType) String() string { return xyz; } </code></pre></pre>semi-: <pre><p>You can, but you can not write them onto other package&#39;s structs as far as I know (without forking and modifying their package, anyways).</p> <p>What you could do is embed someone elses struct into your own type and add your own String, like <a href="http://play.golang.org/p/jVw2zkb3GU">this</a></p> <p>Of course you then cant use your type in functions that want their type, so you may be better off just making your own TheirStructToString() function, depending on what you&#39;re trying to do.</p></pre>tkreadit: <pre><p>Correct, you can only define methods on local types, you can&#39;t just take a type from another package and add methods to it. Imagine if this were allowed and you used a few 3rd party libraries that all added a method f() to an existing type T. When you actually tried to call t.f() where t is an instance of T, which one would be called? You can do embedding or you can define a new local type that you can add methods to:</p> <p>type MyType T</p> <p>But then you have to deal with a lot of type conversions (because MyType and T are different types, it&#39;s not just an alias) which gets annoying quickly.</p> <p>It&#39;s easier to just define a function that takes the type T and you can call it f(t) instead of f.t() Of course, if you need T to implement a certain interface then the only choice you have is for the author of T to make it implement the interface.</p></pre>ejayben: <pre><p>thats lame!</p></pre>jerf: <pre><p>It&#39;s the &#34;orphan instance problem&#34;, and it&#39;s actually a really hard problem to solve. Superficially, allowing it seems appealing, but it actually comes back to bite you hard if you do. It goes beyond merely things like &#34;if two people implement the same method which do you pick?&#34; There&#39;s also things like &#34;if package A implements interface A.B on type C.D, and package E implements E.F on C.D, but A.B and E.F fundamentally violate each other&#39;s contract, how do you resolve this problem?&#34;</p> <p>And the worst part is, the languages that just shrug and start implementing Pragmatic Solutions (TM) have all discovered that these problems and more actually come up in practice, not just in theory. It&#39;s still an open problem in both theoretical and practical programming language theory.</p> <p>To the extent your &#34;thats lame!&#34; stems from something like &#34;I could do it in Ruby&#34;, well, that&#39;s precisely the sort of mess Go is designed from the get-go to avoid. Ruby very easily snarls into an unmaintainable mess if you deeply use monkeypatching.</p></pre>gogolang: <pre><p>What are you using those strings for? Depending on the use case, json.Marshal and json.Unmarshal might be a good solution if you want the ability to easily bidirectionally convert to string and back.</p></pre>

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

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