Remix.run Logo
porridgeraisin 4 days ago

> std-lib

Yes, My favourite is the `time` package. It's just so elegant how it's just a number under there, the nominal type system truly shines. And using it is a treat. What do you mean I can do `+= 8*time.Hour` :D

tux3 4 days ago | parent | next [-]

Unfortunately it doesn't have error handling, so when you do += 8 hours and it fails, it won't return a Go error, it won't throw a Go exception, it just silently does the wrong thing (clamp the duration) and hope you don't notice...

It's simplistic and that's nice for small tools or scripts, but at scale it becomes really brittle since none of the edge cases are handled

arethuza 4 days ago | parent [-]

When would that fail - if the resulting time is before the minimum time or after the maximum time?

tux3 4 days ago | parent [-]

I thankfully found out when writing unit tests instead of in production. In Go time.Time has a much higher range than time.Duration, so it's very easy to have an overflow when you take a time difference. But there's also no error returned in general when manipulating time.Duration, you have to remember to check carefully around each operation to know if it risks going out of range.

Internally time.Duration is a single 64bit count, while time.Time is two more complicated 64bit fields plus a location

porridgeraisin 3 days ago | parent [-]

How is it easy to have an overflow? time.Duration is capped to +- 290 years IIRC.

candiddevmike 4 days ago | parent | prev | next [-]

The way Go parses time strings by default is insane though, even the maintainers regret it. It's a textbook example of being too clever.

nkozyra 4 days ago | parent [-]

By choosing default values instead of templatized values?

Other than having to periodically remember what 0-padded milliseconds are or whatever this isn't a huge deal.

mdaniel 3 days ago | parent [-]

I'm not OP, but I also got tripped up the first time I saw time.Parse("2006-01-02 03:04:05") and was like what the actual?!

https://pkg.go.dev/time#Layout

peterashford 2 days ago | parent [-]

Yeah, that's ugly as fuck. I hate it

pansa2 4 days ago | parent | prev [-]

As long as you don’t need to do `hours := 8` and `+= hours * time.Hour`. Incredibly the only way to get that multiplication to work is to cast `hours` to a `time.Duration`.

In Go, `int * Duration = error`, but `Duration * Duration = Duration`!

porridgeraisin 3 days ago | parent [-]

That is consistent though. Constants take type based on context, so 8 * time.Hour has 8 as a time.Duration.

If you have an int variable hours := 8, you have to cast it before multiplying.

This is also true for simple int and float operations.

  f := 2.0
  3 * f
is valid, but x := 3 would need float64(x)*f to be valid. Same is true for addition etc.
throwawaymaths 3 days ago | parent [-]

It's also completely insane if youve ever done any scientific work.

porridgeraisin 2 days ago | parent [-]

Apart from the extra verbosity, what gives?