tag:blogger.com,1999:blog-7854892290437883216.post2329885277368934620..comments2023-04-07T23:51:07.346+12:00Comments on How Bazaar: Stunned by GoTim Penhey (thumper)http://www.blogger.com/profile/09872376538882273724noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-7854892290437883216.post-82780202870508643272013-07-19T01:56:48.598+12:002013-07-19T01:56:48.598+12:00a work-around is to wrap the reader to an ioutil.N...a work-around is to wrap the reader to an ioutil.NopCloserYi DENGhttps://www.blogger.com/profile/14160396608979133205noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-57891890986257239712013-07-18T16:38:05.171+12:002013-07-18T16:38:05.171+12:00Maybe you can relate to my little, affectionate ra...Maybe you can relate to my little, affectionate rant about the encoding/csv package... http://mwholt.blogspot.com/2013/07/why-yes-gogolang-i-still-want-to-read.htmlAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-65969847677179218582013-07-18T15:48:53.948+12:002013-07-18T15:48:53.948+12:00ALWAYS BE CLOSING.ALWAYS BE CLOSING.Anonymoushttps://www.blogger.com/profile/12916414304823732003noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-61429267835077231862013-07-18T14:54:01.235+12:002013-07-18T14:54:01.235+12:00If they don't want to fix it because it could ...If they don't want to fix it because it could break legacy code, I suppose that's understandable, but then they should add a ReadNoClose method as a stop gap, to make later refactoring easier if they ever do change it.gryftirhttps://www.blogger.com/profile/06259419086877092820noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-6588487738920949472013-07-18T14:26:38.070+12:002013-07-18T14:26:38.070+12:00@rsc thank you very much for the detailed reply.
...@rsc thank you very much for the detailed reply.<br /><br />I only found out today that Rog had brought this up on the dev list as I don't follow golang-dev. I think Rog brought it up because of this issue I hit.<br /><br />I am pleased to hear that the expected behaviour of functions is what I expect, and that this particular issue is an aberration, and not considered OK.<br /><br />I'm pleased that Go has a strong stance on backwards compatibility, and I think documenting this at least will be helpful. Preferably along with the sample code to how to avoid the Close being called (i.e. wrapping in a struct that only exposes io.Reader. Tim Penhey (thumper)https://www.blogger.com/profile/09872376538882273724noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-9388133252117570382013-07-18T14:18:20.605+12:002013-07-18T14:18:20.605+12:00Go developer here.
This is a mistake, plain and s...Go developer here.<br /><br />This is a mistake, plain and simple. It was pointed out on the Go developer mailing list a few days before your post, and you can see <a href="https://groups.google.com/d/msg/golang-dev/o9i_SbGRrzI/n4FPqT1eLlYJ" rel="nofollow">my reply</a> there.<br /><br />NewRequest should take an io.ReadCloser. Unfortunately, due to backwards compatibility, a long standing semantic mistake like this is not something we can just fix, but we've at least <a href="https://codereview.appspot.com/11432044/" rel="nofollow">documented it</a>.<br /><br />The tweet you quoted is wrong, and I want to explain why. If an interface value v is passed to a function f, then what does happen from time to time is that f will look for custom methods on v that are at least logically equivalent to the static interface type f is declared to expect. For example, io.Copy takes an io.Reader and an io.Writer and does the obvious thing, Reading into a buffer and then passing that buffer to Write. Of course, it would be nice to bypass the buffer when possible, and so there is a standard WriterTo interface that an io.Reader can also implement that, in contrast to Read, which copies into a buffer, says "read the data out of yourself and directly into this Writer". If io.Copy finds that method, it will use it, but the operation - reading - is the same. There is an analogous case for the Writer too. If you pass a value v to json.Marshal, Marshal will check to see if v implements json.Marshaler, meaning v knows how to marshal itself as JSON, in which case v is given that opportunity. Again, same operation you requested.<br /><br />In contrast, if you have an io.Reader, while it might be okay to look for other Read-like methods, it is certainly not okay to look for Close. That's a very different operation, it's surprising, and it shouldn't be there. FWIW, I'm not aware of any other instances of this kind of semantic mixup in the standard library. But again, unfortunately, we can't change it until Go 2. All we can do for now is document it and move on.rschttps://www.blogger.com/profile/09449562785422464948noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-67278366520454553632013-07-18T13:30:47.749+12:002013-07-18T13:30:47.749+12:00How unfortunate. This occurs throughout the standa...How unfortunate. This occurs throughout the standard library too. Anonymoushttps://www.blogger.com/profile/13829996874605560287noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-81114320955919190962013-07-18T12:40:51.931+12:002013-07-18T12:40:51.931+12:00It seems as though the correct solution would be t...It seems as though the correct solution would be to simply take a ReadCloser and if someone only had a reader, it would be on them to wrap their reader with a type that has a noop close method.Nate Finchhttps://www.blogger.com/profile/10929290360726095997noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-54971462423582815912013-07-18T12:26:25.190+12:002013-07-18T12:26:25.190+12:00This comment has been removed by the author.jaybuffhttps://www.blogger.com/profile/12775272674690707276noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-32887840435147769432013-07-18T12:26:20.663+12:002013-07-18T12:26:20.663+12:00http://en.wikipedia.org/wiki/Action_at_a_distance_...http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming)jaybuffhttps://www.blogger.com/profile/12775272674690707276noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-12113664147364266802013-07-18T12:24:41.922+12:002013-07-18T12:24:41.922+12:00@Tom Burdick I don't know the specifics in Go ...@Tom Burdick I don't know the specifics in Go but closing a file can have noticeable side effects. It could cause the last bits of data to be written out e.g. fclose() in C can fail just like fwrite(). <br /><br />Also freeing the file descriptor can reclaim disk space when the file is unlinked or allow the file to be overwritten on Windows.<br /><br />Also closing one end of a socket or a pipe cause the other end to see the end-of-file.<br /><br />So you probably don't want to leave closing to the GC, even RAII style object lifetime can lead to bad surprises if you don't think about it.<br /><br />Again I don't know how any of this applies to GO...Alexandre Jasminhttps://www.blogger.com/profile/09292609947064691118noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-70158467892353606972013-07-18T12:10:09.583+12:002013-07-18T12:10:09.583+12:00Andrew, I'm pleased it isn't really normal...Andrew, I'm pleased it isn't really normal in Go. That would just freak me out. I ended up tweeting about it when I found out, and was genuinely surprised when someone said that this wasn't abnormal. The very minimum should be updated documentation, with a clear indication that Close will be called, and preferably with a work around if you don't want that. I used:<br /><br />justReader := &struct{io.Reader}{theReader}<br /><br />That worked, and is now also in our test suite.<br />Tim Penhey (thumper)https://www.blogger.com/profile/09872376538882273724noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-15045423659382960322013-07-18T12:05:23.714+12:002013-07-18T12:05:23.714+12:00It's not really normal in Go. We were surprise...It's not really normal in Go. We were surprised by it when it came up, and had to document it as an extraordinary case.Andrew Gerrandhttps://www.blogger.com/profile/15812461665025191460noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-81492477022171416972013-07-18T10:45:44.477+12:002013-07-18T10:45:44.477+12:00Unexpected mutation is exactly why functional lang...Unexpected mutation is exactly why functional languages are such a joy in some cases... and a pain in others.<br /><br />In other news why is a file descriptor ever closed before all references are lost?Anonymoushttps://www.blogger.com/profile/09508522554438503002noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-8966501293536767782013-07-17T19:24:03.047+12:002013-07-17T19:24:03.047+12:00If this is normal in Go, my question is, how are y...If this is normal in Go, my question is, how are you supposed to know what is called and when? Do I have to start naming my methods in odd ways to make sure Go libraries don't call things unexpectedly?<br /><br />It's crazy.Julian Edwardshttps://www.blogger.com/profile/04494343208322133959noreply@blogger.comtag:blogger.com,1999:blog-7854892290437883216.post-11306326072392871992013-07-17T18:30:37.196+12:002013-07-17T18:30:37.196+12:00Stunned is the word. If this were a real-world co...Stunned is the word. If this were a real-world contract, you'd be filing charges for fraud! :)<br /><br />(Fraud: engaging in a contract without the intention to live up to it. Or at least that's what I learned.)<br /><br />Is it not so bad if the method doesn't modify any state? I don't think it makes a difference. Your method might still read something that's also being updated concurrently. If you have no reason to expect that method to be called here, you can't be expected to prevent a concurrency bug.Jeroen Vermeulenhttps://www.blogger.com/profile/14621263178886380233noreply@blogger.com