Readit News logoReadit News
mseepgood · 4 years ago
It's a type alias, introduced for generics. By the way, Go 1.18 Beta 1 is released (with generics): https://groups.google.com/g/golang-announce/c/eAjK4Oezs_A
exdsq · 4 years ago
How is generics not a big enough change to warrant 2.0?

Edit: I’m impressed generics aren’t a breaking change! I thought this changed Interface{} to Any as a breaking change

philwelch · 4 years ago
In semantic versioning, going from 1.X to 2.X is only indicated when there are incompatible API changes. Adding generics doesn’t break compatibility with preexisting Go code, so it’s unnecessary to increment the major version.
mseepgood · 4 years ago
They are backwards compatible and don't break people's code, so it's 1.x.
bastardoperator · 4 years ago
See https://semver.org/ for more details. https://0ver.org/ is fairly popular, and I see https://calver.org/ pretty often too.
planb · 4 years ago
Was "any" a reserved word in Go before? Because if not, this would be a breaking chnage for all code that uses a var named "any".
preseinger · 4 years ago
It's not a breaking change.
egeozcan · 4 years ago
AFAICT, its usage is not restricted to generics. It seems to be suggested to use anywhere you would use interface{}.

For the release announcement: https://news.ycombinator.com/item?id=29556646

mseepgood · 4 years ago
Yes, it's not restricted to generics. But the reason the alias was introduced is generics. Because they use interfaces to specify bounds (constraints) for type parameters (bounded polymorphism): [T fmt.Stringer], [T io.Reader], ...

So an unbounded type parameter is [T interface{}], or [T any] when using the shorter alias. It's a type alias / predeclared identifier defined in the universe scope:

   type any = interface{}

lolive · 4 years ago
Disclaimer: I am totally newbie in Go. But quite experienced in Java and Js/Ts.

I never jumped the Go bandwagon because of the lack of generics. Can I now try Go?

The following article seems to say that the lack of other features can be frustrating (the lack of lambdas and the lack of the functional handling of collections seems problematic to me)

Also I wonder whether the language has a IDE support as good as IntelliJ with Java (safe function extraction, type-safe autocomplete)

Would the local gurus here please comment?

[the idea for me is to replace my tricky shell scripts with Go scripts.]

https://medium.com/webstep/a-java-developers-adventures-thro...

bearcherian · 4 years ago
If you're main problem with a new language is that it's not written like the language you are used to, you're not going to be happy with the new language.
skybrian · 4 years ago
Go has function literals, which are basically lambdas but a bit more verbose. Typical Go style doesn’t use them as often as other languages. You might assign one to a variable, giving you an inner function. But loops are usually written as for loops, not map calls. One API call that comes to mind where you might use one is ast.Inspect. [1]

Go often works well for replacing shell scripts, even without generics.

[1] https://pkg.go.dev/go/ast#Inspect

drvd · 4 years ago
> I am [...] quite experienced in Java and Js/Ts. > I never jumped the Go bandwagon because of the lack of generics. > Can I now try Go?

Probably no. You still would be very disappointed. Go's take at writing and maintaining software often is pretty repugnant to people with a strong Java or JavaScript mindset. If missing user defined parametric polymorphism ("generics") was a reason to not even _try_ it you will be offended by by other things Go does in its particular way. Be it error handling, pattern matching, concurrency, mutability, etc. Basically if you try to write Java (or JavaScript) programs in Go you will suffer and hate Go. Same for C++/Rust aficionados. Go's newly added "generics" still come without "library support".

ImprobableTruth · 4 years ago
flippinburgers · 4 years ago
The lack of generics was never really a problem to begin with.
zxcq544 · 4 years ago
For IDE you can try goland(which is Intellij Idea for go). For replacing shell scripts go should be fine. It's closer to C than Java, so you will often write "if err!=nil" which is not a problem actually. Go feels like C with Hashmaps and simplified threading.
selljamhere · 4 years ago
> Also I wonder whether the language has a IDE support as good as IntelliJ with Java (safe function extraction, type-safe autocomplete)

Jet Brains makes GoLand, which is about as good as they come. It should feel familiar if you're used to IntelliJ. https://www.jetbrains.com/go/

Dead Comment

kbd · 4 years ago
This is fantastic. It'll make Go feel much less weird. eg from the diff:

  []interface{}{1, 2.0, "hi"} -> []any{1, 2.0, "hi"}
Now that Go is going to have generics, all we need is sugar syntax for early return on error -- like more modern languages such as Rust and Zig have -- and Go may finally be pleasant to program in!

hbn · 4 years ago
It's definitely more streamlined, but my concern would be that newcomers might not understand that it's just an alias. Learning Go really reframed my concept of what an interface is, and I thought that using an empty interface to represent "any type" was kind of ingenious, and helps reinforce its ethos.

An empty interface can represent any type because every type inherently implements an interface with no methods. And that's what Go is all about -- implicitly implementing interfaces.

If a newbie hops into Go and just starts using "any" I think they might assume it's a magic type that's at the base of everything, missing out on the fact that they're still taking advantage of interfaces.

benhoyt · 4 years ago
Counterpoint: I'm an experienced Go dev but still think of "interface{}" as a semi-special "any" type, just because it fits my brain better conceptually. "Any type" is simpler than "an interface with an empty method set, which is of course matched by any type". I think this is a win.
pawelmurias · 4 years ago
A language shouldnt be optimized towards doc avoiding newbies at the cost of making things verbose and ugly.
valenterry · 4 years ago
> I thought that using an empty interface to represent "any type" was kind of ingenious

It makes me a bit sad to read that. We all are on a journey to be become better developers every day. But things like that are like a distraction. They make you think you found a really cool and smart concept, but you actually didn't and it's essentially just a hack.

Not sure what the solution can be. But PL designers should be more clear about features that are just "hacks" and considered "bad" but necessary in practice due to certain constraints. Go's {} and nil-errorhandling are examples. Nulls (in any language) are another common example.

Waterluvian · 4 years ago
This is valuable for a learning language and for learning in general. But it’s the kind of concept that ought to be abstracted away, in my opinion.
egeozcan · 4 years ago
I kind of understand what you mean, as it's similar to what happened with prototypes and the late-comer class syntax in JavaScript, and in that case, it was a net positive change as most would probably say.

Let's see how this plays out.

nightowl_games · 4 years ago
I'm an experienced programmer whos just learning go now and I never made the connection that interface{} meant 'an interface with no methods'. I've always thought 'interface{}' was the clearest wart on the language. Languages shouldn't be about teaching me things, they are just a tool. Keyboard input goes in, computer instructions come out. any is easier to read, more intuitive in its meaning and takes less keyboard input.
chmod775 · 4 years ago
> Learning Go really reframed my concept of what an interface is, and I thought that using an empty interface to represent "any type" was kind of ingenious

There's a few other languages out there that work that way. The split is probably is probably 20/80. Though "popular" languages heavily learn towards Java-esque interfaces - with TypeScript and Go being the odd ones in that bunch.

eru · 4 years ago
> It's definitely more streamlined, but my concern would be that newcomers might not understand that it's just an alias.

Having lots of syntactic sugar works out OK for Haskell.

For example, in Haskell straight-line imperative looking code is an alias for some underlying callback hell.

linkdd · 4 years ago
I cannot wait for the Result monad.

The state of error handling in Go at the moment is embarrassing at best.

the_duke · 4 years ago
Emulating sum types in languages without pattern matching is extremely awkward, to the point of being almost useless.

type Result[T] struct { ok: *T err: error }

Great, so how do you work with it?

* You can have a `ok()` getter that returns `*T`. Now you you need an `if x != nil`

* `isOk()` + `isErr()`

* `unwrap() T`, which panics on errors

* `split() (*T, err)` that splits into separate values, especially awkward since you both need `if err != nil` AND dereference the pointer

That API is more awkward then the status quo, and doesn't buy you any correctness guarantees because eventually you have to do an `if x := res.ok(); x != nil` or `x, err := res.split(); if err != nil {` anyway.

Pretty much the only convenience you gain are functions like `map()` or `unwrap_or`, but eventually you always have to take out the value and without being able to pattern match you can't get an API that improves correctness much.

(std::optional in C++ is a great example)

tptacek · 4 years ago
A lot of people are going to write very un-idiomatic Go code with "Result" types built on simple generics that, 5 years from now, we'll all be kind of smirking at. Rust's Option and Result make sense because the language supports it (most importantly with match statements). They don't make sense here.
Thaxll · 4 years ago
Well it's better than most language with exceptions.

People makes it a big deal, in reality it's not.

papito · 4 years ago
People downvote it, but it's true. 2/3 of your Go code is `if err` blocks. And the way you have to chain the error messages to make the stack make any kind of sense is just maddening.
rp1 · 4 years ago
I’ve been doing a lot of rust programming recently, but how exactly is the Result monad better? I feel like I end up with nested match statements for chained results, but maybe I’m doing something wrong.
BatteryMountain · 4 years ago
Can you kindly post a snippet of what you want the early return on error syntax sugar to look like? I'm trying to map it in my mind on how I'd do it in C# and how it would look in Go.
nvarsj · 4 years ago
Yes, please, the iferr pattern drives me nuts. While I built a few years of my career on golang, I'm absolutely sick of the language at this point. At least we finally get generics.
politician · 4 years ago
Writing code for the happy path is 1/100th of programming. Maybe less.
Cthulhu_ · 4 years ago
What alternative do you propose?
kubb · 4 years ago
I would also like discriminated unions, and a more sane approach to code generation than go generate and writing your own binary that parses source and spits out source code.
rp1 · 4 years ago
The Go code parsing libraries are quite good though. Not sure what else you could want re. code generation.
wejick · 4 years ago
what's not sane about go generate? could you elaborate
Cthulhu_ · 4 years ago
> all we need is sugar syntax for early return on error -- like more modern languages such as Rust and Zig have -- and Go may finally be pleasant to program in!

Can you provide an example? What's wrong with `return err`? That's a very explicit early return on error, no magic or language features (= added complexity) needed.

moth-fuzz · 4 years ago
I'm not sure I like this change. I liked interface{} since it just works out naturally from Go's relatively simple type system, and anyone could come to the conclusion without actually being told "use interface{} to represent any possible value" just by having an understanding of that type system. Adding what is simply a type alias, multiple words for the same underlying concept, to me just feels like jargon. I admire Go for its simplicity and clarity and this change gives me anxiety that that will be obfuscated.
xh-dude · 4 years ago
I don’t think the concern is unreasonable at all but ‘any’ feels pretty solid as far as I’ve had the chance to poke around. There’s some tensions where I think ‘any’ is arguably much simpler:

The baseline is that constraints aren’t best expressed as interface literals in situ. Unlike exceptional use of ‘interface{}’, ‘any’ will be a more naturally invoked constraint.

Also, some of the uses of constraints rely on a unification involving an ‘any’ term that cancels out. Here, the use of ‘interface{}’ is not incorrect but maybe indirect.

zemo · 4 years ago
with generics you wind up with two parameter lists, and type parameters have metatypes. All type parameters need to have a metatype, and the metatype `any` comes up a lot. Once you start using generics you'll start to feel the pain of writing `interface{}` in those signatures, especially when you are dealing with functions like this one:

    func doSomething[X interface{}, Y Fooer[interface{}]](v X, src Y) error {
    }
versus:

    func doSomething[X any, Y Fooer[any]](v X, src Y) error {
    }
the signatures can get long pretty quickly when you have more than one type parameter.

pishpash · 4 years ago
Does a personal (not language-wide)

  type any = interface{}
not work, if you felt that strongly?

eadmund · 4 years ago
I agree with you right now, but I wonder if I will change my mind after having had some experience using the new generics. Maybe it will feel more natural then?
takeda · 4 years ago
Isn't Any essentially:

type Any interface{}

?

throwaway894345 · 4 years ago
I'm pretty sure it's an alias, so: `type any = interface{}`.

`type any interface{}` would declare a new type, while an alias is exactly another name for the same type.

erdaniels · 4 years ago
It's a type alias so it's

    type any = interface{}
That means they're interchangeable compared to defining a new type.

Laremere · 4 years ago
Close, it's:

    type Any = interface{}
That is, it's an alias and casting is not necessary.

Deleted Comment

welder · 4 years ago
Good, now we just need the ability to declare function parameters and return values non-nullable (Forbid passing nil into a function, and declare a function will never return nil).

That would get rid of the "panic: runtime error: invalid memory address or nil pointer dereference" errors.

https://wakatime.com/blog/48-go-desperately-needs-nil-safe-t...

jchw · 4 years ago
I’d kill for union types as well.

… and pattern matching. Maybe just some extensions for `switch`.

… and one of the `try` proposals.

That having been said… I do appreciate that Go has gotten where it is today by being radically simple, and that a lot of extreme care needs to be done to add new features to the language. It’s hard to draw a firm line in the sand. I feel like all of these features would work great together, though; it’d enable Go to do something like `Result` in Rust with few language-level changes.

I even remain somewhat skeptical about generics, but I am hopeful.

weatherlight · 4 years ago
I agree. I don't understand why the designers wouldn't want the language to be expressive. Wouldn't it be better to have an expressive language with conventions than one that's as rigid as it is today?
masklinn · 4 years ago
> I’d kill for union types as well.

> … and pattern matching. Maybe just some extensions for `switch`.

Go has type switches which are… ok. If it were possible to “close up” interfaces and type switches took that in account (match completeness) you’d be done about done, you would not have the structural / patterned unpacking but that’s probably less of a concern.

halfmatthalfcat · 4 years ago
At that point, let's just write Scala.
Cthulhu_ · 4 years ago
> Good, now we just need the ability to declare function parameters and return values non-nullable

But that's already possible, just declare arguments and return values as values instead of references. I mean you'll get the zero value if you don't use those functions properly, but those won't cause nil pointer dereference errors.

I mean, it's a tradeoff between performance and developer competency. To be harsh, I think nil pointer dereferences are developer error, not a flaw in the language.

Deleted Comment

maxk42 · 4 years ago
So now that go has generics and modules, is there an up-to-date intro for writing cutting-edge Go code for people who are already pretty familiar with the older styles?
mseepgood · 4 years ago
There is lots of tutorial-style documentation on modules: https://go.dev/doc/#developing-modules

There is also a tutorial on generics: https://go.dev/doc/tutorial/generics

maxk42 · 4 years ago
I tried doing the modules tutorial a while back but had difficulty with the directory structure. At some point I think the "recommended" directory structure became mandatory and I don't think my personal dev environment ever quite lined-up with it. Perhaps I should wait another year then buy a book.
vlunkr · 4 years ago
While it's good to get up-to-date, I don't think anyone should go re-write code or radically change their programming style to use generics. There's no need to over-complicate things. Anywhere that you're either copy-pasting a bunch, or using code generation might be a good fit for generics.
jcadam · 4 years ago
Just you try not being up-to-date in a coding interview.
makeworld · 4 years ago
I wrote a tutorial on Go Modules, hope it's helpful.

https://www.makeworld.space/2020/11/go_modules.html

Looking for a tutorial on generics myself.

Ericson2314 · 4 years ago
C++, Java, JavaScript, Python, Ruby, Go, now all with popular and/or official type checkers which support generic.

The normie PL bar is rising, slowly but surely.

skohan · 4 years ago
Next let’s do ADT’s
Ericson2314 · 4 years ago
Indeed! C++ got std::variant, Python got....some sort of pattern matching, so there's hope?
rackjack · 4 years ago
I'd really like it if Github handled massive commits like this one better. The way they present it is not very pleasant to navigate.
gepoch · 4 years ago
Same.. This is just a mirror though, so at least you can browse it more sanely over on Gerrit.

https://go-review.googlesource.com/c/go/+/368254

blahgeek · 4 years ago
gofmt -w -r 'interface{} -> any' src

Is this a real command? If so, I’m very impressed. Is there any equivalent for c++ and other languages?

zmj · 4 years ago
Yep, it's a rewrite rule: https://pkg.go.dev/cmd/gofmt

The combination of unambiguous syntax and consistently-formatted code results in rewrites producing meaningful diffs (most of the time).

jamincan · 4 years ago
'cargo fix' will upgrade your code from one Rust edition to the next as well as apply corrections for lint warnings.
ainar-g · 4 years ago
cargo fix is closer to (and possibly inspired by?) go fix[1], imo.

[1]: https://pkg.go.dev/cmd/go#hdr-Update_packages_to_use_new_API...

tjalfi · 4 years ago
IntelliJ, Resharper, and presumably Rider have structural search and replace[0]. It's available for at least C#, Java, and Kotlin.

[0] https://www.jetbrains.com/help/idea/structural-search-and-re...