News for hackers. Stuff that matters.
Re:Map[string]interface{} in Go: a user's manual by tgsovlerkhgsel on Monday July 26, 2021 @05:50PM (#27965928)

    try:
      val = input['foo']['bar']
    except KeyError, TypeError:
      raise HttpErrors.BadRequest
Re:Map[string]interface{} in Go: a user's manual by Kocrachon on Monday July 26, 2021 @06:07PM (#27966091)
Can someone explain to me why python uses try/except so often? I see that promoted as a solution instead of;

if 'bar' in input['foo'].keys(): val = input['foo']['bar']

Generally, exceptions cause code to run slower and I feel like in any other language is considered bad practices.

I never understood why Python promotes EAFP vs LBYL. Both performance and accuracy wise, checking before doing is safer and faster performance.

Re:Map[string]interface{} in Go: a user's manual by kortex on Monday July 26, 2021 @07:43PM (#27966915)
Well, firstly input.get("foo", {}).get("bar", default) is a bit nicer, imho.

Python exceptions are only slower on the exception. They are almost exactly the same speed on success.

LBYL forces you to look for all the ways in which you might leap. EAFP lets you handle even unexpected conditions. The classic use case is checking if a condition exists, then doing the thing, except the condition changed between check and run. So you gotta catch anyways.

I've been moving away from this actually and towards a rust-like Result[T, Exception]. I'm using the package called "result". For fastapi api_request -> handler -> some_func_chain -> return response_to_client patterns, if something barfs, you normally get a 422 and useless "Internal server error". It's far simpler imho to map over some Results and then pack the error(s) into a more useful response.

Also testing is just a lot simpler.

https://pypi.org/project/result/

Re:Map[string]interface{} in Go: a user's manual by tgsovlerkhgsel on Monday July 26, 2021 @06:15PM (#27966161)
Your example will throw a KeyError if "input" doesn't contain "foo", and an AttributeError if "foo" is some unexpected data type that doesn't have keys().
Re:Map[string]interface{} in Go: a user's manual by tptacek on Monday July 26, 2021 @06:10PM (#27966124)
You just generated a 502, and spent a bunch of extra lines doing it. The 502 is bad, and if that's all I need to do, I get that almost for free from net/http's panic handler. It sounds like you don't actually have a problem here.
Re:Map[string]interface{} in Go: a user's manual by tgsovlerkhgsel on Monday July 26, 2021 @06:23PM (#27966222)
I kept the example simple, of course I could now customize the error message further (or take some other sensible action). Note that I returned a 400, not a generic 502 here. If I didn't care at all, I wouldn't need any extra lines. Does the panic handler send a response at all, or does it just drop the connection?

Also, in Go, using panic/recover is considered unidiomatic. You can use it like an exception system, but it's not what you're supposed to do.

Re:Map[string]interface{} in Go: a user's manual by tptacek on Monday July 26, 2021 @06:29PM (#27966266)
I'm not suggesting that you would build a custom exception recovery system; I'm pointing out that net/http, which is definitionally idiomatic, already has that recovery mechanism.
Re:Map[string]interface{} in Go: a user's manual by tgsovlerkhgsel on Monday July 26, 2021 @07:01PM (#27966558)
I believe that that recovery mechanism isn't supposed to be routinely triggered just due to bad user input, and that code that does so would be considered defective.
Re:Map[string]interface{} in Go: a user's manual by tptacek on Monday July 26, 2021 @08:36PM (#27967284)
It's doing almost literally the same thing as the Python code upthread. Just, with less code.
Re:Map[string]interface{} in Go: a user's manual by claudiawerner on Monday July 26, 2021 @06:22PM (#27966209)
I think that was more of an example. There are lots of ways to fail gracefully when you don't have the data you want in the dict.
Re:Map[string]interface{} in Go: a user's manual by tptacek on Monday July 26, 2021 @06:28PM (#27966254)
Right, which is why json.Unmarshal returns an error, and why map lookups return an extra `ok` value in Go.
Re:Map[string]interface{} in Go: a user's manual by tgsovlerkhgsel on Monday July 26, 2021 @07:03PM (#27966569)
It would be a lot more than 4 lines in Go though. Either the struct definition, or a lot of `if !ok return error`. Especially once the nesting gets deeper.
Re:Map[string]interface{} in Go: a user's manual by tptacek on Monday July 26, 2021 @07:29PM (#27966797)
I'm pretty sure it would just be an `if err != nil {http.Error(w, err.Error(), 501); return }`.
Re:Map[string]interface{} in Go: a user's manual by tgsovlerkhgsel on Monday July 26, 2021 @11:19PM (#27968251)
one of these for each nesting level.