Struct initilaization with private variables

5,063 views
Skip to first unread message

Scott Lawrence

unread,
Sep 12, 2010, 7:53:10 PM9/12/10
to golan...@googlegroups.com
This has probably come up already, but I couldn't find anything about
it, so...

type T struct {
Variable string
private int
}

Now &T{"a"} produces the error message "too few values in struct
initializer", and &T{"a", 3} produces no error message at all. The fact
that the former form isn't allowed is somewhat inconvenient; the fact
that the latter is allowed seems like a bug.

Is there a reason struct initializers are done this way?

nsf

unread,
Sep 12, 2010, 8:12:38 PM9/12/10
to golan...@googlegroups.com

I think you're wrong, it's not a bug. If the field is private it means
that it will not be visible outside of the package boundaries and you
can't construct the T using composite literal in other than the current
package. In fact you can't access that private field directly at all
from any other package.

Steven

unread,
Sep 12, 2010, 8:19:51 PM9/12/10
to Scott Lawrence, golan...@googlegroups.com
Private variables are package private. If you were to try initializing a struct from another package this way, you would get an error. If you want to assign selectively to public variables, you can do:

t := &T{Variable: "a"}

A common idiom is for a package to provide a factory function for its types that need initialization:
func NewT() *T { return &T{"a", 3} }
...
t := NewT()

Or an initializer function (less common, but still used):
func (t *T) Init() *T { *t := T{"a", 3}; return t }
...
t := new(T).Init()
OR
t := new(T)
t.Init()

You could also include parameters in the function/method signatures to allow the user to provide values required for initialization.

fango

unread,
Sep 12, 2010, 11:37:26 PM9/12/10
to golang-nuts
As in below example adapted from embedding section of `Effective Go`


package main

import (
"os"
"log"
)
type Job struct {
*log.Logger
size int
b []byte
}

func main(){
x := &Job{
log.New(os.Stderr, nil, "Job: ", log.Ldate),
0, nil, // is it really necessary ?
}
x.size = 2
x.b = make([]byte, x.size)
x.Logf("Job size=%d", x.size)
}

Suppose the Job is a much larger struct embedding *log as the first
field, and maybe more embeddings follow. It would be easier to just
initialize these embeds by composite literal, and default remaining
(unspecified) fields to zero values so as to set them appropriate
later.

Less typing, and clearer code.

Cheers,
Fango

Russ Cox

unread,
Sep 13, 2010, 12:18:33 AM9/13/10
to fango, golang-nuts
>        x := &Job{
>                log.New(os.Stderr, nil, "Job: ", log.Ldate),
>                0, nil, // is it really necessary ?
>        }

Yes, it is. You can omit fields, but if you do
Go asks that you name the fields you're intending
to list, so that it's clear which ones you intended
to supply and that it isn't just a matter of forgetting one.

       x := &Job{
               Logger: log.New(os.Stderr, nil, "Job: ", log.Ldate),
       }

Russ

Reply all
Reply to author
Forward
0 new messages