Go is not Python, not Java, not Ruby, not any other language
that claims to have a type system and then lets people do
whatever they want instead. Go has very strict rules about
separation of packages so that you can build true module
boundaries. If the field is unexported, you can't set it using
reflection, plain and simple.
Yes, it can be surprising that when Go says unexported it
really means unexported and not "you have to work a little
harder to edit data local to that package". However, there
are many things about Go that are surprising if you are
coming from other languages, and if we changed them all
we'd have Python or Java or Ruby and not Go.
Russ
A benefit of this hard boundary between exported and unexported names is that the implementation really is inaccessible. If you want to make any part of it available to another package you *must* design (or at least think about) an appropriate API for doing so.
Russ
Inferring from your answers, It seems the "GO" answer is that: A type which may be serialized (encoded and later decoded) will have to be designed for it from the start. Complete state should be in exported fields. Structs where its full data is only accessible through exported methods or with some unexported anonymous fields cannot be safely/completely encoded/decoded. Hello, data transfer objects design pattern (http://en.wikipedia.org/wiki/Data_transfer_object)
Yes, the benefit for exported/unexported is clear with respect to disallowing access from other packages. The only issue is with situations where you need to encode/decode a struct, e.g. for rpc, or otherwise.
On Tue, Nov 1, 2011 at 4:40 PM, Ugorji Nwoke <ugo...@gmail.com> wrote:
>
>
> On Tuesday, November 1, 2011 12:57:30 AM UTC-4, Russ Cox wrote:
>>
>> On Mon, Oct 31, 2011 at 19:50, Ugorji Nwoke <ugo...@gmail.com> wrote:
>> > However, I think we should reconsider supporting setting private fields
>> > and
>> > *maybe* calling private methods using reflection. (P.S. Private methods
>> > calling is more for symetry. I don't have a compelling use case for it).
>>
>> Go is not Python, not Java, not Ruby, not any other language
>> that claims to have a type system and then lets people do
>> whatever they want instead. Go has very strict rules about
>> separation of packages so that you can build true module
>> boundaries. If the field is unexported, you can't set it using
>> reflection, plain and simple.
>>
>> Yes, it can be surprising that when Go says unexported it
>> really means unexported and not "you have to work a little
>> harder to edit data local to that package". However, there
>> are many things about Go that are surprising if you are
>> coming from other languages, and if we changed them all
>> we'd have Python or Java or Ruby and not Go.
>
> I'm not recommending changing everything in GO to be like what Python or
> Java or Ruby provide. I like just about everything in GO just as it is.
> In this thread, I wrote in detail about areas where this limitation affects
> - types with unexported fields accessible via exported accessor methods
> cannot be serialized (encoded/decoded)
they can.
these types just need to implement the GobDecoder/GobEncoder interfaces:
http://golang.org/pkg/gob/#GobDecoder
same-ish for e.g. json:
http://golang.org/pkg/json/#Marshaler
-s
> Yes, implementing the encode/decode yourself is definitely an option, though not one I am fond of. Recreating the functionality that gob/json package provides for encoding/decoding is not trivial, especially if you just need to include a few more fields in the stream.
Embedding is your friend. Hand gob a wrapper struct that embeds the struct, and in the wrapper include copies of the private data you wish to transmit.
-rob
On Tue, Nov 1, 2011 at 8:40 AM, Ugorji Nwoke <ugo...@gmail.com> wrote:Inferring from your answers, It seems the "GO" answer is that: A type which may be serialized (encoded and later decoded) will have to be designed for it from the start. Complete state should be in exported fields. Structs where its full data is only accessible through exported methods or with some unexported anonymous fields cannot be safely/completely encoded/decoded. Hello, data transfer objects design pattern (http://en.wikipedia.org/wiki/Data_transfer_object)It is generally unsafe to serialize and transport a data structure that has not been designed to support this. For example, if the data structure has an int that corresponds to a file descriptor (this is just one very simple example). My experience is that you design data structures for export (in Go, perhaps even putting in explicit tags to say how to export it).
- Support struct tag which says that a field should not be serialized (encoded/decoded). JSON, GOB, etc will respect such a tag.
Yes, the benefit for exported/unexported is clear with respect to disallowing access from other packages. The only issue is with situations where you need to encode/decode a struct, e.g. for rpc, or otherwise.I disagree. The only case I see it as annoying is when I am trying to write test code to help me diagnose a problem. For example, DeepEqual doesn't quite do what I would hope it would do for testing for precisely this issue. I don't see this as an issue for exportation of data but of the exporter. The gob package skips over data that isn't exported.
-rob
- Document that only json and gob encode/decode will support the encode/decode of unexported fields.