Return an empty struct

10,392 views
Skip to first unread message

Joan Miller

unread,
Apr 10, 2010, 8:16:48 AM4/10/10
to golang-nuts
How to return an empty struct?

My function has to return that struct but if it doesn't find the data
then it has to return it empty:
--------
type bar struct { ... }

func (db *foo) Get(num uint32) *bar {
....

// Return an empty struct
var d bar
return d{}
}
--------

The error message is:
d is not a type

Alexander Surma

unread,
Apr 10, 2010, 8:23:38 AM4/10/10
to Joan Miller, golang-nuts
> var d bar
Declaring the variable 'd' of the type 'bar'
> return d{}
returning an struct of the type 'd' with default values.

You don't have a type named 'd', you want to write:
> return d

You *really* should read the specs more carefully.
Your questions are becoming more and more trivial each day

Surma

chris dollin

unread,
Apr 10, 2010, 8:25:20 AM4/10/10
to Joan Miller, golang-nuts
On 10 April 2010 13:16, Joan Miller <pelo...@gmail.com> wrote:
How to return an empty struct?

Do you mean a struct with no fields, or a struct with its
zero value?


My function has to return that struct but if it doesn't find the data
then it has to return it empty:
--------
type bar struct { ... }

func (db *foo) Get(num uint32) *bar {

You're returning a pointer, not a struct at all. Is
that what you meant?

 
   ....

   // Return an empty struct
   var d bar
   return d{}
}
--------

The error message is:
 d is not a type

And quite right too: d is a variable of type foo,
not a type. (The go compiler's messages are
usually pretty good -- thanks, writers!) The
construct T{V1 ... Vn} requires T to be a type.
 
You can either

  return d
or
  return bar{}

If you really meant the pointer type after all

  return &d
  return &bar{}

--
Chris "it's in the documentation" Dollin

Joan Miller

unread,
Apr 10, 2010, 8:26:17 AM4/10/10
to golang-nuts

On 10 abr, 12:23, Alexander Surma <alexander.su...@googlemail.com>
wrote:

Indeed, in the Go spec. says:

// An empty struct.
struct {}

http://golang.org/doc/go_spec.html#Struct_types

chris dollin

unread,
Apr 10, 2010, 8:40:38 AM4/10/10
to Joan Miller, golang-nuts

Your example (if we ignore the pointer on the return type)
was returning a bar, and a bar is

   type bar struct { ... }

which usually is what we write to say "a struct with
some fields that I'm not going to talk about", not an
empty struct for which you would say

  type bar struct {}

Are you saying that bar is supposed to be an
empty struct?

--
Chris "allusive" Dollin

Joan Miller

unread,
Apr 10, 2010, 8:52:08 AM4/10/10
to golang-nuts

On 10 abr, 12:25, chris dollin <ehog.he...@googlemail.com> wrote:


> On 10 April 2010 13:16, Joan Miller <pelok...@gmail.com> wrote:
>
> > How to return an empty struct?
>
> Do you mean a struct with no fields, or a struct with its
> zero value?

The best one to know easily if there is not data return by that
function.

> > My function has to return that struct but if it doesn't find the data
> > then it has to return it empty:
> > --------
> > type bar struct { ... }
>
> > func (db *foo) Get(num uint32) *bar {
>
> You're returning a pointer, not a struct at all. Is
> that what you meant?

Yes right, it's a pointer. In my code it returns a pointer.

> >    ....
>
> >    // Return an empty struct
> >    var d bar
> >    return d{}
> > }
> > --------
>
> > The error message is:
> >  d is not a type
>
> And quite right too: d is a variable of type foo,
> not a type. (The go compiler's messages are
> usually pretty good -- thanks, writers!) The
> construct T{V1 ... Vn} requires T to be a type.
>
> You can either
>
>   return d
> or
>   return bar{}
>
> If you really meant the pointer type after all
>
>   return &d
>   return &bar{}

Thanks, it works using
return &bar{}

Joan Miller

unread,
Apr 10, 2010, 8:57:39 AM4/10/10
to golang-nuts

On 10 abr, 12:40, chris dollin <ehog.he...@googlemail.com> wrote:

If the function finds the data then it returns bar with its fields.

If that data is not found, then it has to return an empty struct (bar)
to know that it was not found.

chris dollin

unread,
Apr 10, 2010, 9:02:49 AM4/10/10
to Joan Miller, golang-nuts
On 10 April 2010 13:52, Joan Miller <pelo...@gmail.com> wrote:


On 10 abr, 12:25, chris dollin <ehog.he...@googlemail.com> wrote:
> On 10 April 2010 13:16, Joan Miller <pelok...@gmail.com> wrote:
>
> > How to return an empty struct?
>
> Do you mean a struct with no fields, or a struct with its
> zero value?
The best one to know easily if there is not data return by that
function.

Return two results, one your struct (or a pointer to it), the
other a boolean saying whether the data is really there
or not.

This is a standard Go idiom. It's introduced in the tutorial,
discussed in Effective Go, and defined (a little tersely) in
the spec. How did you miss it?

--
Chris "allusive" Dollin

Joan Miller

unread,
Apr 10, 2010, 9:06:13 AM4/10/10
to golang-nuts

On 10 abr, 13:02, chris dollin <ehog.he...@googlemail.com> wrote:


> On 10 April 2010 13:52, Joan Miller <pelok...@gmail.com> wrote:
>
>
>
> > On 10 abr, 12:25, chris dollin <ehog.he...@googlemail.com> wrote:
> > > On 10 April 2010 13:16, Joan Miller <pelok...@gmail.com> wrote:
>
> > > > How to return an empty struct?
>
> > > Do you mean a struct with no fields, or a struct with its
> > > zero value?
> > The best one to know easily if there is not data return by that
> > function.
>
> Return two results, one your struct (or a pointer to it), the
> other a boolean saying whether the data is really there
> or not.

For this case, it's more simple returns one only value for then to
check if that struct is empty or not.

chris dollin

unread,
Apr 10, 2010, 9:08:58 AM4/10/10
to Joan Miller, golang-nuts
On 10 April 2010 13:57, Joan Miller <pelo...@gmail.com> wrote:
If the function finds the data then it returns bar with its fields.

If that data is not found, then it has to return an empty struct (bar)
to know that it was not found.

Not an option.

a bar /always/ has its fields. It's just that if you don't
set them to anything else, they have their type's zero
value.

If the zero values are good enough to tell you what you
need to know, that's OK. But often they won't,

--
Chris "allusive" Dollin

chris dollin

unread,
Apr 10, 2010, 9:14:47 AM4/10/10
to Joan Miller, golang-nuts

What do you mean by "that struct is empty or not"? Do you
mean "contains only zero values"? "Contains at least one
zero value"? "Field X has its zero value"?
 
If you want to test whether the struct is empty that way, you're
going to have to write something like

  result := callMyFunction( withSomeArguments )
  if result.zeroIfEmpty == theZeroValue { whatever ... }

If you return two results its

  result, ok := callMyFunction( withSomeArguments )
  if !ok { ... whatever }

or even

  if result, ok := callMyFunction( withSomeArguments ); !ok { ... }

Neither is remarkably "simpler" than the other, but the
two-results approach seems in this case to be rather
clearer.

--
Chris "allusive" Dollin

Peter Bourgon

unread,
Apr 10, 2010, 9:49:25 AM4/10/10
to golang-nuts
On Sat, Apr 10, 2010 at 2:52 PM, Joan Miller <pelo...@gmail.com> wrote:
> Thanks, it works using
>  return &bar{}

In the failure case, you're creating an instance of a struct with
default values, and expecting the client to somehow check every field
for validity? That's insane. Have you not worked in a language with
pointers before? Since you're returning a pointer, why don't you just
return nil? Or, better yet, why don't you do what practically every
example in the documentation does and use the comma-ok or comma-err
idiom?

Joan Miller

unread,
Apr 10, 2010, 10:51:14 AM4/10/10
to golang-nuts

On 10 abr, 13:49, Peter Bourgon <peterbour...@gmail.com> wrote:

I've not worked into a language with pointers and it's being something
frustrating for me (until I get used).

Esko Luontola

unread,
Apr 10, 2010, 12:36:20 PM4/10/10
to golang-nuts
On Apr 10, 5:51 pm, Joan Miller <pelok...@gmail.com> wrote:
> I've not worked into a language with pointers

What is that language?

Charles Hixson

unread,
Apr 11, 2010, 2:57:11 AM4/11/10
to golang-nuts
I think that Ruby, Python, and Smalltalk are such languages. In Java,
also, most programmers don't deal with pointers. It's unusual in D.
I'm not sure it's possible in Snobal. Etc.

Lots of languages either don't have pointers, or discourage their use.
Personally, while I agree that it's often quite a good idea to have
pointers (depending heavily on language design), the better languages
strongly discourage using them. The profligate use of pointers is one
of the real weaknesses of C & C++.

OTOH, I don't understand go pointers yet. So far it looks as if they
are tightly constrained in how they can be used. If such is the case,
then their use is more a syntactic wart than a real problem. (E.g.,
given that go is a garbage collected language, I'm presuming that one
can't use a pointer to index beyond the bounds of an array that it is
defined on. If you can, this is a major weakness.)


chris dollin

unread,
Apr 11, 2010, 3:23:02 AM4/11/10
to Charles Hixson, golang-nuts
On 11 April 2010 07:57, Charles Hixson <charle...@earthlink.net> wrote:
Esko Luontola wrote:
On Apr 10, 5:51 pm, Joan Miller <pelok...@gmail.com> wrote:
 
I've not worked into a language with pointers
   
What is that language?
I think that Ruby, Python, and Smalltalk are such languages.  In Java, also, most programmers don't deal with pointers.  It's unusual in D.  I'm not sure it's possible in Snobal.  Etc.

It depends what you call "pointers", as well.

Java, for example, is littered with pointers; they're the
only way to use instances of classes. `new` delivers
a pointer to a freshly-constructed object. You can tell
they're pointers, not object values, by copying them and
seeing that the "copy" changes when the original does.

What Java (Ruby, Python, Smalltalk) /doesn't/ have is
/pointer arithmetic/ or /value objects/.


OTOH, I don't understand go pointers yet.

Go pointers point to some thing - a variable, a struct
field, an array element -- and allow you to read & change
it "from elsewhere". That's it. They're an essential part of
eg the method system, since they allow you to write methods
that update the receiver.

 So far it looks as if they are tightly constrained in how they can be used.  

Indeed: no arithmetic.
 
If such is the case, then their use is more a syntactic wart than a real problem.  

Why a "syntactic wart"? The semantics of such pointers is
pretty much essential in an imperative language, and
having syntax to reflect it doesn't strike me as particularly
warty.

(E.g., given that go is a garbage collected language, I'm presuming that one can't use a pointer to index beyond the bounds of an array that it is defined on.  If you can, this is a major  weakness.)

You can't. No arithmetic. Yay!

Chris

--
Chris "allusive" Dollin

Charles Hixson

unread,
Apr 11, 2010, 3:36:42 AM4/11/10
to golang-nuts
chris dollin wrote:
> On 11 April 2010 07:57, Charles Hixson <charle...@earthlink.net
> <mailto:charle...@earthlink.net>> wrote:
> ...

>
> If such is the case, then their use is more a syntactic wart than
> a real problem.
>
>
> Why a "syntactic wart"? The semantics of such pointers is
> pretty much essential in an imperative language, and
> having syntax to reflect it doesn't strike me as particularly
> warty.
If you come from a C or C++ background, then I can understand this.
You've gotten used to them. But a wart it is, and it causes lots of
problems to people who aren't accustomed to them. All the other
languages that I mentioned (except, perhaps, Snobal) actually use
pointers, but the programmers don't need to deal with them beyond
remembering that they are handled differently from, say, integers (in
Smalltalk even this wart is handled, but it's computationally
expensive). When one needs to remember (or figure out) where to use *p
and where to use &p, then it's a syntactic wart. It's a place where
lots of people make mistakes that cause them problems. Eventually they
get used to it and stop noticing that it's a problem, but it remains
there to trip people up. Occasionally even experienced users.
>
> ...
>
>
> ...

chris dollin

unread,
Apr 11, 2010, 4:15:32 AM4/11/10
to Charles Hixson, golang-nuts
On 11 April 2010 08:36, Charles Hixson <charle...@earthlink.net> wrote:
chris dollin wrote:
On 11 April 2010 07:57, Charles Hixson <charle...@earthlink.net <mailto:charle...@earthlink.net>> wrote:
...


   If such is the case, then their use is more a syntactic wart than
   a real problem.  

Why a "syntactic wart"? The semantics of such pointers is
pretty much essential in an imperative language, and
having syntax to reflect it doesn't strike me as particularly
warty.
If you come from a C or C++ background, then I can understand this.  

Algol, Fortan, Algol W, BCPL, Pascal, Algol 68, RTL/2,
Pop11, Prolog ... all before I learned C.

You've gotten used to them. But a wart it is, and it causes lots of problems to people who aren't accustomed to them.  

This is true of very many features of programming
languages: ints vs floats vs decimals vs bignums,
overflow, order of evaluation (or not), typing rules,
meaning of while loops, assignment, why semicolons
are needed (or not), thesignificanceofspaces, how store
is managed (or not), etc.

All the other languages that I mentioned (except, perhaps, Snobal) actually use pointers, but the programmers don't need to deal with them beyond remembering that they are handled differently from, say, integers (in Smalltalk even this wart is handled, but it's computationally expensive).

And those languages don't have value types. You don't
get to pass around a struct {int, int} value, only a pointer
to it. You don't get to pass around an array [3] float64.
only a pointer to one, and the 3 gets lost as part of the type
and turns into a run-time-only value. Go allows you to
do this and that choice is -- I believe, has to be -- reflected
in the syntax.

Maybe the choice isn't a good one to put into a language,
but that would be a different argument.

Maybe the compiler could do more in the way of inference,
but I think people would still need to be able to express
their choice:

  func (this TTT) brew( y int ) { ... }

TTT might be some type X or instead *X. Which do you
want? It makes a difference. If you want the compiler to
choose for you, what are the rules for making that choice?
Are you sure they're not as confusing to newcomers as
the existence and use of *T?

--
Chris "allusive" Dollin

Charles Hixson

unread,
Apr 12, 2010, 4:19:25 PM4/12/10
to chris dollin, golang-nuts
chris dollin wrote:
> On 11 April 2010 08:36, Charles Hixson <charle...@earthlink.net
> <mailto:charle...@earthlink.net>> wrote:
>
> chris dollin wrote:
>
> On 11 April 2010 07:57, Charles Hixson
> <charle...@earthlink.net
> <mailto:charle...@earthlink.net>
> <mailto:charle...@earthlink.net
D definitely has value types. And you *can* pass structs (and possibly
static arrays [i.e., arrays that are of a size defined at compile
time]). Java also has value types, though they tend to be less used,
because they are more awkward.

>
> Maybe the choice isn't a good one to put into a language,
> but that would be a different argument.
>
> Maybe the compiler could do more in the way of inference,
> but I think people would still need to be able to express
> their choice:
>
> func (this TTT) brew( y int ) { ... }
>
> TTT might be some type X or instead *X. Which do you
> want? It makes a difference. If you want the compiler to
> choose for you, what are the rules for making that choice?
> Are you sure they're not as confusing to newcomers as
> the existence and use of *T?
>
> --
> Chris "allusive" Dollin
The basic idea here is that a reference type is a different type from
the type it references...and the compiler knows which type each variable
is, and whether it can do an automatic conversion. So, being Cish:
int *xp, x;
then the compiler knows that if you write:
xp = x
that can only mean store the address of x into xp, and conversely. This
means that the only "syntax" one need for referencing or dereferencing
is the declaration and something equivalent to the dot-notation (e.g.
a.b.catapult(c)) and c will be automatically referenced or dereferenced
to fit the function declaration.

So it's no less powerful, and it's easier and more intuitive. (One
still needs to be wary about multiple references to the same mutable
object, of course.)

chris dollin

unread,
Apr 12, 2010, 4:29:46 PM4/12/10
to Charles Hixson, golang-nuts
On 12 April 2010 21:19, Charles Hixson <charle...@earthlink.net> wrote:

And those languages don't have value types. You don't
get to pass around a struct {int, int} value, only a pointer
to it. You don't get to pass around an array [3] float64.
only a pointer to one, and the 3 gets lost as part of the type
and turns into a run-time-only value. Go allows you to
do this and that choice is -- I believe, has to be -- reflected
in the syntax.
D definitely has value types.

Fair catch -- I don't know D and forgot to exclude it above.

 
 And you *can* pass structs (and possibly static arrays [i.e., arrays that are of a size defined at compile time]).  Java also has value types, though they tend to be less used, because they are more awkward.

Java has non-primitive value types? Which ones?


Maybe the compiler could do more in the way of inference,
but I think people would still need to be able to express
their choice:

 func (this TTT) brew( y int ) { ... }

TTT might be some type X or instead *X. Which do you
want? It makes a difference. If you want the compiler to
choose for you, what are the rules for making that choice?
Are you sure they're not as confusing to newcomers as
the existence and use of *T?

The basic idea here is that a reference type is a different type from the type it references...and the compiler knows which type each variable is,

All this is true of Go types.
 
and whether it can do an automatic conversion.   So, being Cish:
int  *xp, x;
then the compiler knows that if you write:
  xp = x
that can only mean store the address of x into xp, and conversely.  This means that the only "syntax" one need for referencing or dereferencing is the declaration and something equivalent to the dot-notation (e.g. a.b.catapult(c)) and c will be automatically referenced or dereferenced to fit the function declaration.

So it's no less powerful, and it's easier and more intuitive.

And doesn't allow you to disambiguate xp1 = xp2,
as I said elsewhere.

(Algol68, a language which was astonishingly fond of
implicit coercions, and which conflated the notions of
variable & reference to provide pleasing elegance with
razor-wire, would lead you merrily into this trap; at least
it gave you a way out as well.)

Chris

--
Chris "allusive" Dollin

Daniel Smith

unread,
Apr 12, 2010, 4:32:01 PM4/12/10
to Charles Hixson, chris dollin, golang-nuts
On Mon, Apr 12, 2010 at 3:19 PM, Charles Hixson <charle...@earthlink.net> wrote:
The basic idea here is that a reference type is a different type from the type it references...and the compiler knows which type each variable is, and whether it can do an automatic conversion.   So, being Cish:
int  *xp, x;
then the compiler knows that if you write:
  xp = x
that can only mean store the address of x into xp, and conversely.

How does it know you don't want whatever xp references to be set to x?

xp = &x; //if it's this by default...
*xp = x; //how do you make it do this?


--
Daniel Smith
http://www.schaumburggoclub.org/
Reply all
Reply to author
Forward
0 new messages