You are agreeing with me. A type switch on concrete types (that you control) is far different than using an available Len() method and assuming the same semantics.
> On Feb 7, 2019, at 1:05 AM, Dan Kortschak <d...@kortschak.io> wrote: > > Addressing the first sentence, it was a direct answer to a comment you > made: > >> But is it really? If you read the description for Len() on >> bytes.Buffer it is the length of unread portion. But that doesn’t >> mean the buffer isn’t just a portion of the entire body - it can be a >> chunk which is continually reloaded. > > As far as the claim that there is a need to have a Len method in > io.Reader, have a look at the code in question. It type asserts on > three concrete types that are known to the function, all three have a > Len method and this is used to obtain the known length. All other > io.Readers are considered to have an unknown length. > > Whether it's wrong to use Len depends on whether there is a generally > accepted and consistent set of semantics to Len() int. There is. This > is strengthened if the use of an existing Len method is noted in the > docs. > >> On Wed, 2019-02-06 at 15:50 -0600, robert engels wrote: >> I am not sure what that has to do with the discussion. My point was >> that for it to be applicable here, it needs to be defined as part of >> io.Reader, since that is what Body is declared as. It is not, so >> using in the manner outlined is not correct IMO. >> >>> >>> On Feb 6, 2019, at 3:37 PM, Dan Kortschak <d...@kortschak.io> wrote: >>> >>> The generalised semantics of Len are that it returns the number of >>> available elements in the collection, being a cognate of the len >>> built- >>> in. This means that as you consume elements from a buffer, the Len >>> value reduces. This is directly equivalent to >>> >>> for len(buf) != 0 { >>> println(buf[0]) >>> buf = buf[1:] >>> } >>> >>>> On Wed, 2019-02-06 at 08:56 -0600, Robert Engels wrote: >>>> >>>> But is it really? If you read the description for Len() on >>>> bytes.Buffer it is the length of unread portion. But that doesn’t >>>> mean the buffer isn’t just a portion of the entire body - it can >>>> be a >>>> chunk which is continually reloaded. >>>> >>>> This is the danger in using private APIs publically based upon >>>> the >>>> existence of a method - it leads to very brittle code - and there >>>> are >>>> almost certainly better ways to design it to avoid these issues. >>>> If >>>> the core api is not expressive enough then it will be more >>>> difficult. >>>> >>>>> >>>>> >>>>> On Feb 6, 2019, at 8:30 AM, Burak Serdar <bser...@ieee.org> >>>>> wrote: >>>>> >>>>>> >>>>>> >>>>>> On Wed, Feb 6, 2019 at 5:15 AM Robert Engels <reng...@ix.netc >>>>>> om.c >>>>>> om> wrote: >>>>>> >>>>>> I see now, but if that can be the case, shouldn’t the Body be >>>>>> documented that the Reader may be a ReaderWithLen, and the >>>>>> consumer is free to type check/cast? If not, you are using >>>>>> internal details that you should not be. >>>>> Yes, the documentation should say if the reader has a Len() >>>>> method >>>>> it >>>>> would be used to set the ContentLength. Len is no longer an >>>>> internal >>>>> detail then. >>>>> >>>>>> >>>>>> >>>>>> >>>>>> This is a problem with Go in general. Because the returned >>>>>> object >>>>>> “implements” some interface because it happens to have the >>>>>> required method, doesn’t mean it was designed to be used that >>>>>> way, or that it has the required semantics - unless >>>>>> documented to >>>>>> have them. >>>>> I agree with you there. Len() is straight forward, but in >>>>> general >>>>> just >>>>> because a function is named something doesn't mean it'll do the >>>>> same >>>>> thing for all implementations. On the other end of the spectrum >>>>> is >>>>> Java-like interfaces where you want explicit inheritance of a >>>>> specific >>>>> interface. I don't know if there's anything in between, but I >>>>> like >>>>> Go's approach much better. >>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Feb 6, 2019, at 2:22 AM, Matteo Biagetti <matteo.biagetti@ >>>>>> gmai >>>>>> l.com> wrote: >>>>>> >>>>>> Make sense, thanks for explanation >>>>>> >>>>>> >>>>>> >>>>>> Il giorno mercoledì 6 febbraio 2019 07:28:54 UTC+1, Burak >>>>>> Serdar >>>>>> ha scritto: >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Tue, Feb 5, 2019 at 8:13 PM robert engels <ren...@ix.net >>>>>>> com. >>>>>>> com> wrote: >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> That’s what I was trying to point out. Your design is not >>>>>>>> correct. The Body is a Reader, not a Buffer - the length >>>>>>>> of >>>>>>>> the request/body may be indeterminate - that is, a >>>>>>>> stream. >>>>>>>> Attempting to get the length of an underlying buffer is >>>>>>>> not >>>>>>>> only probably not possible, but not correct in many >>>>>>>> situations. >>>>>>> The length of the body *may* be indeterminate, and if >>>>>>> that's >>>>>>> the case, >>>>>>> the underlying Reader will not have a Len method. The >>>>>>> design is >>>>>>> to >>>>>>> handle the case where the underlying Reader is a Buffer >>>>>>> with a >>>>>>> Len >>>>>>> method. If the Reader has Len, then the NopCloser derived >>>>>>> from >>>>>>> that >>>>>>> will also have a Len, and NewRequest can set the content >>>>>>> length. If >>>>>>> the Reader does not have Len, then the content length is >>>>>>> unknown. >>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> There is a reason the Body is a ReaderCloser and not a >>>>>>>> buffer. It is part of the http specification. >>>>>>>> >>>>>>>> On Feb 5, 2019, at 9:00 PM, Burak Serdar <bse...@ieee.org >>>>>>>>> >>>>>>>> wrote: >>>>>>>> >>>>>>>> On Tue, Feb 5, 2019 at 7:00 PM Robert Engels <ren...@ix.n >>>>>>>> etco >>>>>>>> m.com> wrote: >>>>>>>> >>>>>>>> >>>>>>>> Shouldn’t you just be taking the content length from the >>>>>>>> header if forwarding the same body. There is no need for >>>>>>>> the >>>>>>>> length of the body. >>>>>>>> >>>>>>>> >>>>>>>> True. What I was suggesting is a fix for the general >>>>>>>> case. >>>>>>>> >>>>>>>> >>>>>>>> On Feb 5, 2019, at 6:53 PM, Burak Serdar <bse...@ieee.org >>>>>>>>> >>>>>>>> wrote: >>>>>>>> >>>>>>>> On Tue, Feb 5, 2019 at 5:18 PM Dan Kortschak <d...@kortsc >>>>>>>> hak. >>>>>>>> io> wrote: >>>>>>>> >>>>>>>> Personally, I think this is a bug in the behaviour of >>>>>>>> NewRequest. See h >>>>>>>> ttps://github.com/golang/go/issues/18117 for some >>>>>>>> additional >>>>>>>> context. >>>>>>>> >>>>>>>> >>>>>>>> Agreed. One solution could be to have: >>>>>>>> >>>>>>>> type HasLen interface { >>>>>>>> int Len() >>>>>>>> } >>>>>>>> >>>>>>>> Then have NopCloser return a nopCloser with len if the >>>>>>>> underlying >>>>>>>> implementation has len, with the obvious changes to >>>>>>>> NewRequest.Ugly, >>>>>>>> but can be done without API changes. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Tue, 2019-02-05 at 05:18 -0800, matteo....@gmail.com >>>>>>>> wrote: >>>>>>>> I've the following situation: >>>>>>>> I proxy a request to another server and when I made a >>>>>>>> POST >>>>>>>> and create >>>>>>>> a new >>>>>>>> request, the contentLength is zero: >>>>>>>> >>>>>>>> req2, _ := http.NewRequest(req.Method, newApiUrl , >>>>>>>> req.Body) >>>>>>>> fmt.Println("New request from body:", >>>>>>>> req2.ContentLength) // >>>>>>>> print 0 >>>>>>>> >>>>>>>> Checking in the source code of the NewRequest func Body >>>>>>>> don't >>>>>>>> respect >>>>>>>> some >>>>>>>> interface and populate the ContentLength field. >>>>>>>> >>>>>>>> Could be a bug? Which could be a valid approach in order >>>>>>>> to >>>>>>>> create a >>>>>>>> new >>>>>>>> request from an existing one and correct set the Body >>>>>>>> length? >>>>>>>> >>>>>>>> A working example here: >>>>>>>> >>>>>>>> https://play.golang.org/p/SvCDLj0NrXb >>>>>>>> >>>>>>>> Thanks! >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to >>>>>>>> the >>>>>>>> Google Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>> from >>>>>>>> it, send an email to golang-nuts...@googlegroups.com. >>>>>>>> For more options, visit https://groups.google.com/d/optou >>>>>>>> t. >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to >>>>>>>> the >>>>>>>> Google Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>> from >>>>>>>> it, send an email to golang-nuts...@googlegroups.com. >>>>>>>> For more options, visit https://groups.google.com/d/optou >>>>>>>> t. >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to >>>>>>>> the >>>>>>>> Google Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>> from >>>>>>>> it, send an email to golang-nuts...@googlegroups.com. >>>>>>>> For more options, visit https://groups.google.com/d/optou >>>>>>>> t. >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to >>>>>>>> the >>>>>>>> Google Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>> from >>>>>>>> it, send an email to golang-nuts...@googlegroups.com. >>>>>>>> For more options, visit https://groups.google.com/d/optou >>>>>>>> t. >>>>>>>> >>>>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the >>>>>> Google Groups "golang-nuts" group. >>>>>> To unsubscribe from this group and stop receiving emails from >>>>>> it, >>>>>> send an email to golang-nuts+unsubscr...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the >>>>>> Google Groups "golang-nuts" group. >>>>>> To unsubscribe from this group and stop receiving emails from >>>>>> it, >>>>>> send an email to golang-nuts+unsubscr...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.