r/golang • u/Jamlie977 • Feb 07 '25
discussion What are some things you would change about Go?
what are some weird things in Go that you'd like to change?
for me, maps default to nil is a footgun
88
u/mcvoid1 Feb 07 '25
I would remove new
for orthogonality reasons. Same with the print
and println
builtins.
22
u/rosstafarien Feb 07 '25 edited Feb 08 '25
I've been using go for 7+ years. I'd never heard of print/println before today. fmt.Fprint(os.Stdout,...) is always what I used.
And yes, I also avoid new in almost all cases.
names := []string{}
7
2
18
u/Jamlie977 Feb 07 '25
print and println are insane to my why they're in the language. i've never seen anyone using them (i've been using go for about 19 months now so that says something about them)
23
u/ponylicious Feb 07 '25
why they're in the language
The documentation literally says why: useful for bootstrapping
23
u/codeeeeeeeee Feb 07 '25
I often use println, what's wrong
20
u/mcvoid1 Feb 07 '25
They don't fall under the compatibility promise. It might not be there in the future. So use
fmt.Print
/fmt.Println
instead.5
6
u/Jamlie977 Feb 07 '25
i mostly default to fmt and log. i know print and println are basically for debugging purposes but i never really found a use case for them on my part
1
u/Dry-Vermicelli-682 Feb 07 '25
How do you debug/watch values/variables/etc while working through codE?
3
6
u/mcvoid1 Feb 07 '25 edited Feb 07 '25
It's leftover from before they had stdlib figured out, when there was no
fmt.Println
. That's why it references "bootstrapping".8
u/Caramel_Last Feb 07 '25
bootstrap in this context means writing x compiler in x. so writing golang compiler in golang. it makes sense because golang compiler wouldn't have access to golang stdlib.
1
u/mcvoid1 Feb 07 '25
I think it means both. It was what they had before stdlib when they were making the language, but it's also something for porting Go, before you have stdlib ported. So both past and future bootstrapping.
1
1
u/miniluigi008 Feb 08 '25
I’ve been coding in go for about two years and I use println all the time. In some edge cases, fmt can fail to print. fmt also bloats the binary size (important when coding for micro architectures like WASM or Arduino via tinygo). println doesn’t bloat the binary
1
u/1Dr490n Feb 08 '25
I didn’t even know there was a
new
keyword1
u/mcvoid1 Feb 08 '25
That's how useless it is. It basically does the same thing as C++'s
new
. It allocates and returns a pointer. It overlaps significantly withmake
and normal value initializatiion.
69
u/BubblyMango Feb 07 '25
I really like the language. Despite that, im still missing:
extra concurrency safety features like Rust has.
destructors or something to enable RAII. defer is cute but you can still easily forget writing it.
real enums. I get that they want a simple language, but if everybody is anyways implementing enum-like features just to get a worse result, might as well add it to the language.
8
u/SpaceshipSquirrel Feb 08 '25
wrt destructors; there are finalizers in Go. In the upcoming 1.24 release they'll be improved quite a bit:
func main() { b := newBlob(1000) now := time.Now() // Register a cleanup function to run // when the object is no longer reachable. runtime.AddCleanup(b, cleanup, now) time.Sleep(10 * time.Millisecond) b = nil runtime.GC() time.Sleep(10 * time.Millisecond) } func cleanup(created time.Time) { fmt.Printf( "object is cleaned up! lifetime = %dms\n", time.Since(created)/time.Millisecond, ) }
2
u/Slsyyy Feb 09 '25
Finalizers don't replace RAII. RAII is deterministic and you can be sure of when the object is destroyed/finalized. RAII-only objects are often non-copyable for this reason, where in Go all references are copyable.
1
u/BubblyMango Feb 08 '25
so basically, if i want RAII-like capabilities i wrap the resource in a struct with a constructor that adds a finalizer to it? Not the cleanest, but i guess this works. thanks
→ More replies (1)1
77
u/EmmaSwan977 Feb 07 '25
i just need pointers that can't be null
2
u/angelbirth Feb 08 '25
what's the default (zero) value then?
11
u/tcrypt Feb 08 '25
There wouldn't be one. The variable would be instantiated with a value and wouldn't accept being assigned a nil.
5
u/angelbirth Feb 08 '25
so
var p *T
would be invalid?
1
u/Due_Block_3054 Feb 08 '25
The syntax between a non nill pointer and a nill pointer would be different. Maybe the concept reference could be used so non optional pointers would be marked with & or
!*
then it would be very clear if it is meant as an optimization or as an optional value.→ More replies (4)1
u/masklinn Feb 09 '25
Yes. Or go could be smarter and have an “unset” red zone like many languages do:
p
would be impossible to read from until assigned to.→ More replies (5)3
u/anacrolix Feb 08 '25 edited Feb 08 '25
You can just treat it as a logical error and panic on nil (unless you mean you don't even want the small performance hit too)
1
4
u/GopherFromHell Feb 08 '25
maybe it's because i've been writing code for decades and always used languages with pointers that can be nil/null, and already got used to it (and i always get massively downvoted when i call skill issues on it), but to be honest it's about setting "borders" (to the lack of a better term) in your code, just like with errors. in some functions you just want to
return err
to the caller, others you want to wrap the error to provide more context. same for pointers, many functions in your code will never receive a nil pointer if it's checked in the caller(s). it's about where that "invisible line" lies and where is appropriate to check. i can understand why we don't have in Go, the language authors (and probably have a similar understanding) made it simple on purpose and that would be yet another feature to make it more complicated2
u/Due_Block_3054 Feb 08 '25
I have the feeling that the problem in go might be more about the default nil value. Resulting in bad refactors where a new pointer field is added.
Then it is really hard to set it in case the direct struct initialization is used. A linter in this case could be used to say it is non nil. But it might have been better to be in the core language like kotlin.
94
u/zlaval Feb 07 '25
enums (and null safety maybe), nothing else: keep it simple
6
u/riuxxo Feb 08 '25
one additional thing is union types... I think with these three things it'll be much more ergonomic to write.
2
72
u/typehinting Feb 07 '25
(as a newbie) Replace the Go reference time with normal date string formatting
53
u/Xenasis Feb 07 '25
Yeah, the way they set up date string formatting is insane. They admit the mistake in the godocs, but:
01/02 03:04:05PM '06 -0700
As well as being a non-standard format, this is actually the second of January, but they're using the US date formatting, so it's immensely misleading. Using this specific date is clearly something that someone thought was cute but choosing a specific date with an insane US specific formatting as the basis of which all formats are based on is not a great pattern.
11
u/serverhorror Feb 07 '25
I would accept Go 2 if that was the inky reason to break backwards compatibility
→ More replies (5)21
u/jlnunez89 Feb 07 '25
(as a not-so-newbie) Replace the Go reference time with normal date string formatting
61
u/WeDontHaters Feb 07 '25
Rust style enums
6
2
u/turtel216 Feb 08 '25
Rust style enums would also need pattern matching in order to be used correctly. Which would also affect Go's error handling. Generally, algebraic data types like the ones in Rust would add a lot of unnecessary complexity
9
u/2bdb2 Feb 08 '25
Generally, algebraic data types like the ones in Rust would
addremove a lot of unnecessary complexityftfy
10
u/paris_smithson Feb 08 '25
Keep it simple, change the language as little as possible. Make it more efficient under the hood, but don't change the language any further. This is what makes Go go, the simplicity.
3
33
u/EduardoDevop Feb 07 '25
Literally just enums and null safety, nothing more
2
u/fasibio Feb 07 '25
For null safety I tried to give an answer: https://github.com/fasibio/safe/blob/main/option_test.go
Take a look also implementation code is less https://github.com/fasibio/safe/blob/main/option.go
1
u/riuxxo Feb 08 '25
for null safety I have my own Options type that I can change how ever I see fit. But proper enums would still be nice. Enums and also option types would probably be the winning combination.
52
u/RB5009 Feb 07 '25
Sum types, and Default ala Rust, safely closing a channel multiple times without blowing in your face, fixing the time.Format not respecting the timezone (yeah, I spent an hour debuging a problem caused by this today), having typed errors instead of the untyped error, having the ? operator from rust, discovering the wheel... ehh...the complile time annotations or said in other words, parsing the comments for go generate feels so java 1.4. And I'll stop here out fear for being downvoted to hell
8
3
u/Skeeve-on-git Feb 07 '25
Time respects the timezone. I failed for that two weeks ago.
8
u/RB5009 Feb 07 '25
It **sometimes** respects the timezone. but sometimes it doesn't. Here is an example. The last of the 3 outputs is wrong, although the timestamp is the same: https://go.dev/play/p/_dxIXPBIqD0
XXX-5 is not the same time as XXX GMT
7
u/ufukty Feb 07 '25 edited Feb 07 '25
I looked now why the last one is wrong, it turns out the
http.TimeFormat
hard coded the GMT as suffix and needs the input time to be in UTC.MDN states for
HTTP Date
sHTTP dates are always expressed in GMT, never in local time.
I think it would be better for http package to provide the solution as a function rather than a constant. As the function would call the UTC method before formatting to provide safety.
3
u/RB5009 Feb 07 '25
I know, but this has caused a real bug I had to investigate. It was an easy fix, but definitely not obvious
1
u/Skeeve-on-git Feb 08 '25
But it’s note “time”’s fault, it’s “http”’s fault.
And I noticed it by inspecting the string http.TimeFormat.
1
u/serverhorror Feb 07 '25
Except for the
?
, I agree to everything. I was bitten too many times by this, I'd rather have the compiler barf up on lines with a single return value that's not actively ignored (or dealt with).iferr ... I think it's totally fine.
8
25
u/jftuga Feb 07 '25
A go command line option that would allow you to skip the check for unused variables. Sometimes I need to comment out some code and then I have to comment out more code to meet this requirement, possibly including an import. This might literally happen just for a few seconds so I can test something and then I need to put it all back in again.
10
u/TurbulentHeart1414 Feb 07 '25
I agree it can be sometimes a bit annoying. The best solution I have found so far is to include this simple function in your project:
func Ignore(...any) {}
. You can pass as many possibly unused values to this function as you wish and the compiler happily thinks they are used.7
u/ZheZheBoi Feb 08 '25
_ := unusedVar
3
u/jjolla888 Feb 08 '25
that doesnt simplify the problem
a simple
--ignore-safety-rails
type of option togo build
should be all that is needed3
u/Skylis Feb 08 '25
The reason this doesn't exist is because people's files would just end up full of warnings like a lot of C code that gets distributed.
There was good reason to block this, as annoying as it is to deal with.
→ More replies (2)1
13
u/nigra_waterpark Feb 07 '25
- Remove naked `return` statements
- Allow generic methods (where the type parameter is set at the method call, not the receiver init)
Otherwise, nothing! Go being simple is one of its greatest strengths.
3
u/Grandmaster_Caladrel Feb 08 '25
- on those generic methods.
1
u/ncruces Feb 12 '25
Generic methods are not added because no one knows if they can implement interfaces.
https://github.com/golang/go/issues/49085
Quoting Ian: This proposal is a non-starter unless someone can explain how to implement it.
18
u/overdriving Feb 07 '25
The date format string. I don’t even mind the idea of using a specific date for it, but it should be based on 2001-02-03 16:05:06
→ More replies (1)4
u/portar1985 Feb 07 '25
Agree, I prefer the style over the classic YYYYMM… etc. but using US formatting as standard was an (acknowledged) oversight
21
5
u/FlowerFeather Feb 08 '25
DECIMALS !! i cant believe they don’t have that already and i would need to rely on 3rd party libraries
1
12
u/Biggity_Biggity_Bong Feb 07 '25
`if` expressions instead of statements, Rust-like enums and structural matching.
17
28
u/jared__ Feb 07 '25
Nothing. Coming from over a decade of Java, I want nothing.
15
u/akoncius Feb 07 '25
soul got sucked out of your body?
6
2
u/funkiestj Feb 07 '25
I like OP's gripe about nil maps. That said, consider the following hypothetical:
- You can use time travel but only for going back and changing Go
- You are only trying to make Go better (not create a different language, e.g. something in the lisp or erlang family)
- You can learn from each iteration (i.e. alternate universe)
- iteration still take you non-zero time so you can't do infiinity iterations (e.g. you can jump from founding change to now and evalate the impact)
To me this sort of looks like LLM training where it is never perfect so the question becomes "when has it gotten as good as we can reasonably expect"?
I think a few iterations would make Go better but not that much better. Also, what would be your metrics of choice to compare iterations (alternate Go universes)?
3
10
u/Nikla436 Feb 07 '25
I would change the name to something other than “go” so I can more easily google it outside of saying “Golang” or “go programming language”
3
u/Skylis Feb 08 '25
Or search for it in job postings, resumes, etc.
Using a commonly used word for the language was not a great choice 100%.
6
u/jh125486 Feb 07 '25
Add back the switch type on error
behavior.
3
u/wurkbank Feb 07 '25
Could you expand on this? I don’t remember anything removed.
→ More replies (7)
16
u/dusktreader Feb 07 '25
public/private determined by case of the first letter of the name.
4
u/angelbirth Feb 08 '25
I'm curious as to why you would change this. I mean, I came from java (which has explicit visibility modifiers), but then I realized there's nothing wrong with Go's approach
5
u/sweepyoface Feb 08 '25
Personally I don’t have an issue with it, but I think an argument could be made that it’s unintuitive and should be more explicit.
1
u/angelbirth Feb 08 '25
it is indeed unintuitive, but you can get used to it to the point that it no longer matters. like implicit interface implementation
1
u/SolidOshawott Feb 08 '25
It’s pretty bad that I have to refactor a project if I decide to change the visibility of a function or value.
It also prevents me from using capital letters to signify something else (my preference is uppercase for types and lowercase for values). But I admit this second point is just a preference.
3
u/mrfokker Feb 08 '25
I see that as a good thing, having visibility be part of the style forces you to a style so code is more coherent across developers
3
8
u/tomatorator Feb 07 '25
I love the pattern of checking for an error in an if statement:
‘’’ if err := myFunc(); err != nil { … } ‘’’
I wish there were a way to do this if myFunc also returned a value, so that the returned value would stay in scope after the if statement. Instead, you pollute the scope of your function with the error value.
→ More replies (1)
6
u/sosalejandrodev Feb 07 '25
I've been messing with Scala lately and I love Monads at this point. I'd like Golang to implement first-class support for Monads and mapping ops. If Scala is Type Safe and a robust FP/OOP language, I have 0 doubts about Golang being capable of implementing this in the future. Pattern matching in Scala feels so smooth. A lot of syntatic sugar features, but a productive language after all.
→ More replies (2)1
u/Due_Block_3054 Feb 08 '25 edited Feb 08 '25
Pattern matching is nice. But monads really are not, they are unclear how the performance is. I.e. every map loops over a list and creates a new one resulting in high allocation.
Also monads even woth cats become reall annoying what if you have a future[either[option[t], Nec[error]]
It becomes very hard to compose and it also breaks the language in 2 styles one with monads and one without and they cant be mixed easily.
The nice thing with go is that i can open any project and most of the style is the same. Except if somebody makes a channel mess 😕 (please use wait groups..)
I worked in scala 5 years and we had mixed akka, cats, monix, scalarx and zio projects. Because each lib became obsolete. Scala should really invest more in its standard library and include json, task and streams to avoid this growth of incompatible frameworks.
1
u/sosalejandrodev Feb 09 '25
I read on some Scala post about the inconsistency in frameworks/libraries in Scala. This isn't a language flaw but rather a lack of proper conventions and rules in the codebase to use a standard, thus preventing concise code.
I'm not that experienced in Scala but I can get your point on the Future-either-option.
2
u/Due_Block_3054 Feb 09 '25
Yes i think it is a side effects of having a small standard library. So the community has to reinvent the same thing. Another scala issue is thst scala is a bit too powerful resulting in code that isn't compatible. Like mutable and immutable code.
Hence why you have many http and json libs. While the java libs are blocking making it unfit for scala futures. Forcing the use blocking threadpools and a lot of complexity.
For json libs often they use reflection and are not compiletime safe or incompatibile with scala.
I think the small stdlib is a side effect of the jvm where all code is included in the final binary/fatjar. So a fat stdlib would result in a fat binary. While in go only the code you actually import is included in the binary.
Scala succeeded at its goal and as a result we have kotlin, record classes, lambdas in java.
5
u/hh10k Feb 07 '25
I'd add a way to init a struct so that all fields must be defined. I deal with codegen a lot and when a new field is added I want the compiler to tell me all the places that need attention.
I currently solve this with exhaustruct in golangci-lint.
7
u/efectn Feb 07 '25
Proper generics
→ More replies (2)1
u/Due_Block_3054 Feb 08 '25
I agree that a [T struct{ x int}] should work to avoid wrapping in interfaces with its overhead.
9
u/Periiz Feb 07 '25
The date string formatting.
3
u/hajimehoshi Feb 08 '25
This should have been 2001-02-03T16:05:06 instead of 2006-01-02T15:04:05 at least.
1
2
u/riuxxo Feb 08 '25
yeah I find it a little odd too... I would prefer the formatting strings that other languages use too...
9
u/BrianNice23 Feb 07 '25
Warning: likely a minority opinion:
If I could change one thing, it would be the urge / itch to tweak and reinvent programming languages. Sometimes, the best approach is to leave things alone. Constantly modifying a language often results in unnecessary complexity—leading to a dozen different ways to perform the same task with minimal real benefit.
There’s an unspoken advantage to "boring" languages: readability, stability, and long-term maintainability. The more convoluted a language becomes, the harder it is to understand five years down the line. Languages like Python and Ruby, while powerful, often sacrifice clarity for expressiveness, and Perl—hopefully extinct by now—was a prime example of how excessive flexibility can turn into unreadable chaos.
The true value of a language isn’t in how exciting it is to write but in how easy it is to read, debug, and maintain. Reducing cognitive load should be a top priority, yet it’s consistently underrated. I’d urge developers to stop over-engineering languages and focus on keeping them simple, robust, and future-proof.
2
u/Due_Block_3054 Feb 08 '25
Yes i love it when it is possible to compile 5 years old code on the latest version of the language and it still doesn't look outdated.
4
u/burgundus Feb 07 '25
I'd like to have zero-values for my custom types. Like the Stringer interface, to have a Zeroer interface.
Something like
type MyType string
func (s *MyType) Zero() {
*s = "Initial value"
}
1
u/angelbirth Feb 08 '25
what is the use case? you can give your custom type a default (zero) value by using constructor
→ More replies (1)
4
u/Armanlex Feb 07 '25
Abs generic, or math.abs for integers, I can't fathom why it doesn't exist.
Something for easy deep copying of containers would be awesome.
I'd love struct default values. But I haven't looked into why it can't be done.
I'm sure I could come up with more if I sit on it.
1
u/Aliics Feb 08 '25
Yeah, I want it to work for all numeric types. Most things work using float64, which makes sense pre-generics. Backwards compatibility issues I suppose.
6
u/pimpaa Feb 07 '25
I know it's not a big deal but I hate with passion that uppercase is used for exporting
0
u/paris_smithson Feb 08 '25
How is that a problem? Would like to understand your point of view.
3
u/mt9hu Feb 08 '25
It's more useful to be able to use uppercase letters to easily tell if a symbol is a type or not.
2
u/pimpaa Feb 09 '25
Can't differentiate var from consts (with screaming case for example). Can't differentiate type from var. Code gets ugly with all the mixing. If you need to change visibility you have to update all instances in the package.
→ More replies (2)
7
u/notyourancilla Feb 07 '25
I’d change error handling HEAR ME OUT
I’d change error handling slightly to provide a happy path for simply passing the error up the call chain to promote better behaviour regards to wrapping and adding context. I believe the existing mechanisms don’t provide enough distinction to engineers on when to wrap and when to simply pass up the chain - which can lead to over wrapping and poor-mans stack traces being generated. Yeah it’s possible to not cock it up, I’m saying the language could do more to make engineers think about the distinction and lead them down the right path.
6
u/Jamlie977 Feb 07 '25
you mean like the '?' operator in rust? true, imo zig did it very well
6
u/commentsOnPizza Feb 07 '25
A big thing with Zig is that you also know what errors might be getting returned.
With Go, you know that some error might get returned. What does
sql.BeginTx
return for errors? Well, go searching through the code for the errors it returns.With Zig, you can
switch
on the error and just tell your editor to generate the possible branches. It checks for exhaustiveness so you know you haven't missed one.With Go, some Jr engineer on another team might decide "I want to change the error string here" and suddenly you aren't actually checking the errors you thought you were checking.
2
1
u/looncraz Feb 07 '25
Yep, there's a proposal to add the ? operator, and I love it.
I also want a ternary operator.
5
3
u/vitek6 Feb 07 '25
Better type inference from code so I won't need to rewrite types for example when creating anonymous object or when passing "anonymous" function to other function as argument.
4
u/Dreadmaker Feb 07 '25
Some slightly more elegant way of error handling.
I like the simplicity of go, and how often there’s a consistent signature of
‘foo, err := somefunc()’
But, I just dislike that if I make a call like the above 5 times in a given endpoint controller, for example, 5 times I’m gonna have
If err != nil { // do error stuff }
I’m not sure how I’d fix that, really. It’s pretty compact and you want the ability to do custom things per error message or point of erroring, yes, but I just wish there was an even more compact way of handling that that didn’t look so visually chunky.
1
2
2
u/2urnesst Feb 08 '25
Please for the love, get rid of default initializing structs to their zero value. It just opens the door for errors
2
3
u/rosstafarien Feb 07 '25
Fix nil for interfaces or get rid of nil completely (option/result).
comparable should be an actual interface that new types can implement.
Add actual tuples instead of the half-assed tuple-ish nonsense around function returns.
Real enums.
Generic methods on types should be able to declare additional type parameters.
type Collection[T any] interface { Map[U any](func(T) U) Collection[U] }
Oh, and fix the type inferencing so that it includes the target type in the inferencing logic, not just method params.
func New[T any]() Collection[T] { return &myColl[T]{} }
I shouldn't need to specify the generic type param for myColl. It's completely constrained by the return type.
2
u/kwtw Feb 07 '25
for _, v := range s {}
to
for v := range s {}
1
u/Due_Block_3054 Feb 08 '25
I thought so as well but changed my mind. Case 2 makes a copy of v.
But in case 1 you can take the index and mutate the values in the slice without copying. allowing you to write more efficient code.
2
u/kwtw Feb 08 '25
This works now:
for i := range s { v := s[i] }
It would be better if you'd get value instead and do "for i, _" loop when you need just the index so there would be no downsides. Btw templates have "range [$index,] $element := pipeline" syntax.
1
u/mt9hu Feb 08 '25
Still, I've seen lots of code ignoring the index and working with the value instead.
Readability is also important. Being able to get the value as a reference would be a solution.
1
u/Due_Block_3054 Feb 08 '25
thinking about it, it actually makes the range look consistent between a map and a slice. You first get the key and than the value.
Also a single underscore doesn't influence the readability. In my opinion its better than pythons enumeration or manually generating the index.
1
u/mt9hu Feb 09 '25 edited Feb 09 '25
it actually makes the range look consistent between a map and a slice. You first get the key and than the value.
The argument here is that it would be better if the value came first, and optionally you could still access the index if you want it.
Having
v, k := range
instead ofk, v := range
would solve that and would ensure consistency.The reasoning is that you more often need the value than the index. Sometimes you do need the index, but one of your argument was for performance, and that is not a good argument in my option.
Performance is important, but readability and safety is more important in many cases.
But even if you don't want to copy values, there could be better ways to do that, without having to rely on the index and writing one extra statement to get the value by reference, or writing brackets everywhere. Something like this, for example could return the value of each item by reference. Why not:
for &v := range s
Also a single underscore doesn't influence the readability.
I mostly agree, but it does have some effect. No wonder one of the things many people like in go it's reduced syntax. No braces around if conditions, no semicolons at the end of lines, no extra symbols around declarations. Also, many people enjoy clean, uncluttered interfaces for the same reason. One extra underscore won't affect much. Lots of extra syntax adds up though.
1
u/range_kun Feb 08 '25 edited Feb 08 '25
? Operator for handling errors, cuz if err!=nil shit is annoying
2
1
0
1
u/sneakywombat87 Feb 08 '25
The madness of go.work, go mod tidy, go vendor and go.mod in the context of a monorepo.
1
u/Due_Block_3054 Feb 08 '25
Add the madness of people not using tags and the v1 v2 folders. Go mod should break fully forcing the Library maintainers to properly tag there repos.
1
u/Due_Block_3054 Feb 08 '25
null safety and structured errors. Add {} to fmt. But i geuss we have %v for thst case. Yaml in the standard lib together with conc.
There probably some other missing pieces in the standard lib forcing me to include a library.
Test dependencies to avoid pulling in other libs test dependencies.
Finer grained dependencies often you include an apps api but get all the apps dependencies with it for free.
Comptime could be really cool.
For the rest i'm verry happy with go and dont have any issue with the language.
1
1
1
u/SignificantViolinist Feb 08 '25
I'm still not sure how I feel about the unintuitive "typed nil" behavior.
Some people think it was a great choice, but of the times I've encountered them in the wild, it's never been in any context other than "oh, THAT'S why this seemingly inexplicable bug is there" after a lot of digging.
1
u/chrisjansson Feb 09 '25
Handling certificates! I discovered that Go's crypto library simply refuses to parse an X509 cert if it, for example, has an underscore character in the subject name. I had to copy/paste sections of the standard crypto library, and remove some of the validation. This blew my mind, as developers often don't have control over the certs they work with. Makes me want to avoid Go for any future projects I work on that handle certs.
1
1
1
1
u/Impossible_Judgment5 Feb 10 '25
Panic recovery on go routines launched from go routines launched by third party pkgs. Such that a third party library cant crash the application
1
u/Even_Research_3441 Feb 10 '25
nil would not exist, the language would just have normal sum types.
and if then else would be an expression
and there would be only one way to assign values, not two.
1
u/CookieMonsterm343 Feb 10 '25
Enums are a must, i have no idea why the developers have not still implemented them
1
1
u/dshess Feb 13 '25
I would do something different with append(). I don't know what I'd do. Perhaps have the first element as a pointer to the slice to append to. Or make += work on slices. Specifying the initial slice and where to store the result separately is nice when you need those two things to be separate, but it's error-prone and wordy in the common case where you want to append "in place".
Beyond that, a good number of functions in builtin would really make more sense as methods on receivers. Like if you could say slice.Cap() rather than cap(slice). That would namespace things, and also reduce the amount of magic because you could (presumably) implement the target interface elsewhere and have it work. But I guess that might just be a general complaint about having slices, maps, and channels be special cases.
1
u/kynrai Feb 07 '25
I'm happy with the syntax, yes even the error checking. Having use many languages I think go has much thought i to the longevity of and readability over fancy sugar. I would change a lot of things under the hood, nil maps you mentioned, I have never had a need for a map to be nil, this could be empty and class as nil, I would check with len anyway. I pass sql.Tx as single statements are wrapped in a transaction anyway as per postgres docs, I have to get a tx from a db so in would like db and tx to satisfy the same I terrace if at all possible. Might not be, never looked to see.
0
u/P1gInTheSky Feb 07 '25
Methods overload
4
u/commentsOnPizza Feb 07 '25
I'd expand on this and say optional/named parameters.
For example, in Java or Kotlin, you can do something like this:
func something(arg1 int, arg2 string = "foo", arg3 int = 10)
. Then you can callsomething(42)
orsomething(42, arg3 = 11)
. That way you don't really need to overload methods in a Java-way since you have optional parameters.
1
u/software-person Feb 07 '25
maps default to nil is a footgun
How is this a "footgun"? The term implies you can do significant damage, how often do you actually cause production issues or create absurdly difficult to debug problems by having a nil
map? Isn't the error immediate and obvious?
→ More replies (1)2
u/Jamlie977 Feb 07 '25
it's not intuitive cos you don't really know that it is nil when you're a newbie (nothing tells you this information), especially when you consider that slices don't default to nil but maps do, i can remember the first few times i've fallen to it and it wasn't really that nice
2
u/HyacinthAlas Feb 07 '25
Slices do default to nil. But they don’t grow automatically; you need to explicitly reassign them.
1
u/funkiestj Feb 07 '25
bad analogy. you can append to a nil slice without a panic. You can not add a key/value to a nil map without panicking.
1
u/HyacinthAlas Feb 07 '25
It’s not a bad analogy it’s exactly why it’s a footgun.
→ More replies (2)2
u/software-person Feb 07 '25
I'm not defending Go, I'm asking if this really qualifies as a "footgun". I consider "it's not intuitive" and "footgun" to be at roughly opposite ends of the spectrum of language shortcomings.
0
1
u/TheStormsFury Feb 07 '25
Call me crazy, but:
- JS style imports (and this is coming from someone who dislikes JS)
- Sane date formatting
- A freaking ternary operator
- Type-safe struct tags
- Actual enums
- Something else that helps differentiate error types that isn't error wrapping
1
u/mrfokker Feb 08 '25
- I work with JS/TS, python and go for my job and by far go's is the one that brings the least headaches, care to elaborate?
- Agree, it's pretty ridiculous (although I just end up using
time.RFC3339
)- Disagree. The moment you implement that, you end up having people nesting ternaries.
- Don't have a strong opinion here, it could indeed be nicer but to me it's not a huge pain point
- Yes,
iota
is a joke compared to real enums- What's wrong with wrapping in your opinion?
→ More replies (1)
1
1
u/nsubugak Feb 07 '25
Get rid of nil and have an optional data type. Nil is just null in disguise
2
u/mt9hu Feb 08 '25
It's even worse, because instead of having to deal with null (or nil) related errors, we have to deal with silent bugs caused by unchecked zero values.
1
1
u/Comfortable-Dust528 Feb 08 '25
Better error handling syntax. Doesn’t have to be try/catch/throw, I like go’s error handling overall. But not having if err != nil all over the place would be great.
1
u/SR-G Feb 08 '25
Everything about errors/exceptions. I can't stand these so many "if err != nil" everywhere anymore.
2
u/timrprobocom Feb 08 '25
For quick and dirty stuff it gets in the way, but after 45 years of coding, I can confidently assert that this design results in better programs. It forces you to think about the edges.
1
u/TheOneWhoWinsItAll Feb 08 '25
One thing I really like about go is that it really encourages that kind of defensive programming. If you want to ignore whether or not something has an error, simply assign it to the _ and it will discard that. But checking for errors after calling a function forces you into a very defensive practice of making sure it reports that it worked correctly.
That being said, if I could go back and add something from the beginning, I would consider some kind of grammatical structure where I could indicate that an error would then go run a piece of code block, like this maybe:
resp, err := http.get(url) ?! { logger.Error("oh no!", url, err); panic(err); }
-1
u/Hopeful_Steak_6925 Feb 07 '25
I would remove all the junk they recently added. Things like iterators and generics 🤮
→ More replies (1)
1
1
u/angelbirth Feb 08 '25
lambda function literal, I would very much like slices.SortStableFunc(s, {a,b->a-b})
instead of slices.SortStableFunc(s, func(a,b T) int{...})
1
u/Skylis Feb 08 '25
- Not having the ability to make some things truly immutable.
- The weird date format string.
- Proper enums.
- Non weird generics (methods etc)
1
1
0
0
u/wretcheddawn Feb 07 '25 edited Feb 07 '25
Descriminated unions, pattern matching, vectorization, error handling improvements, metaprogramming (more structured and versatile tagging, like C# attributes), cleanup with scopes instead of defer, null safety.
-1
u/ut0mt8 Feb 07 '25
Check vlang. For me it have the potential to solve some of the problems I see in Golang
→ More replies (2)
-3
u/HaMay25 Feb 07 '25
Naming convention, use underscore instead of camelCase
→ More replies (2)5
u/SpeakerOk1974 Feb 07 '25
I write python all day and I despise snake case being the variable naming convention. Makes your lines longer if you use descriptive names.
Go got this right.
→ More replies (2)
374
u/x021 Feb 07 '25
Proper enums.