-
-
Save bmizerany/fcd0348bda96edce05a4fc7426e47751 to your computer and use it in GitHub Desktop.
package question | |
func whatsTheEquivalentOfThisWithHandleCheckQuestionMark(w io.Writer) (rN int, err error) { | |
w = LimitedWriter{w, 23} | |
n, err := io.WriteString(w, "some data 1") // 11 bytes written | |
rN += n | |
if err != nil { | |
return err | |
} | |
n, err := io.WriteString(w, "some data 2") // 22 bytes written | |
rN += n | |
if err != nil { | |
return err | |
} | |
n, err := io.WriteString(w, "some data 3") // 23 bytes written: BOOM!!! | |
rN += n | |
return rN, err | |
} | |
func canItBeThisQuestionMark(w io.Writer) (n int, err error) { | |
handle err { return n, err } | |
w = LimitedWriter{w, 23} | |
n += check io.WriteString(w, "some data 1") // 11 bytes written | |
n += check io.WriteString(w, "some data 2") // 22 bytes written | |
n += check io.WriteString(w, "some data 3") // 23 bytes written: BOOM!!! | |
return nil | |
} |
My hope is that canItBeThisQuestionMark
would not compile, and that instead we'd have to write
func canItBeThisQuestionMark(w io.Writer) (n int, err error) {
handle err { return n, err }
w = LimitedWriter{w, 23}
nb := check io.WriteString(w, "some data 1") // 11 bytes written
n += nb
nb = check io.WriteString(w, "some data 2") // 22 bytes written
n += nb
nb = check io.WriteString(w, "some data 3") // 23 bytes written: BOOM!!!
n += nb
return n, nil
}
even though it is not as clean.
@elimisteve your version returns n = 22, not 23, right?
I do not see a problem.
With handle err { return n, err }
, it will return 22, err
With handle err { return n, err }
, it will return 0, err
Programmer is in control. Sometimes it might be exactly what you want. I.e. what if you are consuming data from a socket or pipe, or parsing, and you find an error only at position x. Similarly if the WriteString is to a socket. You can't unread / unwrite this data.
If you are asking about whatever n will be updated, in a situation where WriteString returns (1, SomeError)
, then this 1
will be ignored, and n += 1
, will not be performed.
In a situation like this you would write:
n3, err = io.WriteString(w, "some data 3")
n += n3
check err
maybe?
This is because n += check X()
is rewritten to:
``
temp, err := X()
if err != nil { call handler with err; return; }
n += temp
This is the same as using normal `:=` operator:
``
temp, err := X()
if err != nil { call handler with err; return; }
n := temp
Notice that in Go you can't express assignment to err, and increment of n in a single statement anyway.
It does mean however than
n = check X()
and
n, err = X()
if err != nil { return err; }
do have different semantic (and the first one would use extra register / stack space). This probably only applies to return values tho. In other cases, compiler should be able to do the same as before.
I did not see the semantic explained precisely in current drafts tho.
@kalexmills I'm wondering if the addition is performed before the error passed to
handle
. If it isn't the case that the addition is performed, then will the code I wrote compile? It seems to me this could be something the compiler will aid in catching.