82

I'm still puzzled as why we have new in Go.

When you want to instantiate a struct, you do

t := Thing{}

and you can get a pointer to a new instance by doing

t := &Thing{}

But there's also this possibility :

t := new(Thing)

This last one seems a little alien to the rest of the language. &Thing{} is as clear and concise as new(Thing) and it uses only constructs you often use elsewhere. It's also more extensible as you might change it to &Thing{3} or &Thing{Feets:7}.

In my opinion, having a supplementary keyword1 is costly, it makes the language more complex and adds to what you must know. And it might mask to newcomers what's behind instantiating a struct.

It also makes one more reserved word.

So what's the reasoning behind new ? Is it sometimes useful ? Should we use it ?


1 : Yes, I know it's not a keyword at the grammar level, you can shadow it, but that doesn't change the fact it's, for the reasonable developer, a reserved word.

18
  • 3
    "...to Go coders..." - this is the reason. F#/Haskell/etc. are very alien to C developers and that's why they are getting ~0 traction. Scala made an effort and now it is more approachable and heard of.
    – Den
    Sep 4, 2013 at 8:25
  • 15
    By the same notion, Python and Ruby are very alien to C developers, as they use bunch of unfamiliar keywords, "weird" syntactical rules (where are braces?) and strange semantical concepts (generators? metaclasses? decorators?). Yet they don't get ~0 traction, quite the opposite.
    – Xion
    Sep 4, 2013 at 11:01
  • 8
    @Xion: did you look at the initial growth rate of Ruby? It took ages to get where it is now (18 years, to be precise). Python is even older (1991!). Sep 4, 2013 at 12:05
  • 2
    @AndresF. Some of the resistance to Scala could have nothing to do with the language. As a younger programmer (age 25), something about the name itself makes me think of a cross between a math-based language like Matlab (which I have bad memories of) and a really old one like Fortran. There has never been any urge to even look at it.
    – Izkata
    Nov 3, 2013 at 16:50
  • 5
    A side note: new isn't a keyword in Go. It's a built-in function. Nov 5, 2013 at 8:35

2 Answers 2

67

The best way to ask is probably to the people working on it; exactly what I did!

Tl;dr: it was originally there before make and &{}, and it's still the function to use in some situations.

Basically, here are the most important parts quoted:

So what's the reasoning behind new ? Is it something useful ? Should we use it ?

You cannot do this without new

v := new(int)
*v++
fmt.Println(*v)

new isn't a headline feature of Go, you won't find it used often, but when you need it, it is there.

Cheers

Dave

After another answer showing this kind of solution:

vv := 0
v := &vv
*v++
fmt.Println(*v)

I asked for further clarification:

So basically, Dave's point doesn't really stand?

There are places where it's inconvenient to sneak in a new variable just to take its address.

new(T) has an immediately straightforward meaning, rather than being a multi-step idiom.

Dave's point only falls if mere technical possibility (of doing without new) is compelling on its own.

Wasn't this discussed because it was just obvious that Go should have it because almost every language has it?

The "shall we keep new?" discussion pops up from time to time. Since we can't take it out until Go 2, if I understand the Promise correctly, there doesn't seem to be much to be had from going round the loop again; by the time Go 2 is thinkaboutable, we might have some different and better ideas ...

Chris

It's also there mostly for historical reasons:

you need to consider the history of the project. i think new is introduced first before there is make.

That is true. In fact we struggled for a while before coming up with the idea of make. If you look at the repository logs you can see that make only shows up in January 2009, revision 9a924177598f.

The new builtin function also preceded the idea of &{} for taking the address of a composite literal (and that syntax is in some sense wrong; it probably ought to be (*T){fields of T} but there wasn't enough reason to change it).

The new function is not strictly necessary but code does seem to use it in practice. It's hard to get rid of it at this point.

Ian

6
  • I would be happy to see links to the other "shall we keep new?" discussions which pops up from time to time. Nov 5, 2013 at 14:42
  • Does something prevent you from doing v := &(0) and skipping the temp variable? (I know no Go.) Nov 5, 2013 at 14:48
  • 3
    @AlexFeinman As 0 is a literal constant, you can't take its address. A problem would occur if you'd want a specific type too. That's why a syntax like &int or &int(0) might be useful (didn't think a lot about the best syntax, though). But doing it in two lines as Collins showed is fine too (vv := 0; v := &vv). Nov 5, 2013 at 14:50
  • 22
    "Since we can't take it out until Go 2" ...which, as everyone knows, will never happen because Go 2 is considered harmful. Sep 28, 2016 at 15:34
  • 2
    @MasonWheeler you almost killed me... still laughing at "Go 2 considered harmful"... weirdly enough I was talking about that article today at lunch. Jun 6, 2019 at 0:39
0

In peano.go they do the following:

type Number *Number
func add1(x *Number) *Number  {
     e := new(Number)
     *e = x
     return e
}

and I could rewrite it without using "new" and get the same results:

type Number *Number
func add1(x *Number) *Number {
     var e Number
     e = x
     return &e
}

So even in this very particular case, it does not seem necessary at all.

1
  • run go build -cflags "-m" and I believe you'll see why they chose their solution. If it needs to be more obvious gist.github.com/Lewiscowles1986/… shows the 2 line diff. This can be why unit analysis fails
    – MrMesees
    Apr 21, 2020 at 12:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.