In this case I mean within the boundaries of a single package.

I realize there is no way to enforce another package maintainer to call the 
method wrapper rather than the field directly, but I was wondering if 
people have come up with naming conventions such as a leading underscore to 
make it apparent that certain fields shouldn't be accessed directly under 
most circumstances.  

On Friday, November 17, 2017 at 10:27:05 PM UTC-8, Nicholas Hanley wrote:
>
> In Go, lowercase identifiers are not visible outside the package in which 
> they are defined (ref: Exported identifiers 
> <https://golang.org/ref/spec#Exported_identifiers>). Your example 
> declares foo in the main package but I assume your real code would be in 
> its own package. What you can do is export Foo and GetBar, but leave the 
> bar field unexported.
>
> Your code would look something like this:
> main.go
> package main
>
> import (
> "fmt"
>
> "example.com/baz"
> )
>
> func main() {
> f := baz.Foo{}
> fmt.Printf("f.bar lazy-loaded: %v\n", f.GetBar())
> }
>
> example.com/baz/foo.go
> package baz
>
> type Foo struct {
> bar string
> }
>
> // Method wrapper that does lazy-loading
> func (f *Foo) GetBar() string {
> if f.bar == "" {
> // lazy-load this from a database or some other expensive call
> f.bar = "bar"
> }
> return f.bar
> }
>
>
> On Friday, November 17, 2017 at 4:00:27 PM UTC-5, Traun Leyden wrote:
>>
>>
>>
>> I'm trying to figure out a way to best signal to other developers 
>> maintaining a single package that a field is unsafe to access directly.  In 
>> this case, it's being lazily loaded, and the only way to ensure it will be 
>> properly loaded is to access the method wrapper rather than directly 
>> accessing the field.
>>
>> For example, see this code <https://play.golang.org/p/Y-Qi3D3QwO>:
>>
>> type foo struct {
>>    bar string
>> }
>>
>> // Method wrapper that does lazy-loading
>> func (f *foo) getBar() string {
>>     if f.bar == "" {
>>         // lazy-load this from a database or some other expensive call
>>         f.bar = "bar"
>>     }
>>     return f.bar
>> }
>>
>> func main() {
>> f := foo{}
>> fmt.Printf("f.bar directly: %v\n", f.bar) 
>> fmt.Printf("f.bar lazy-loaded: %v\n", f.getBar()) 
>> }
>>
>>
>> If you access the field directly, you get an empty value.  If you call 
>> the method wrapper, you get the intended value.
>>
>> I believe the official answer is just "do the right thing" since you are 
>> within the package boundaries and have full control.  And I'm pretty sure 
>> the language doesn't provide anything here.  
>>
>> But what I'm wondering -- are there any common conventions or workarounds 
>> to avoid this pitfall?  So far the only idea I've been able to come up with 
>> is to use underscores and/or comments to clearly mark the field as being 
>> unsafe to access directly:
>>
>> type foo struct {
>>    *_bar* string  *// You probably want to use getBar() since this is 
>> lazily loaded an unsafe to access directly.*
>> }
>>
>>
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to