6

As the title says, is accessing public struct fields more idiomatic in Go than getters and setters? Wouldn't that lead to violation of data encapsulation, also public fields in other OO languages like Java are frowned upon.

This answer even claim that getters and setters are not idiomatic in Go.

Does the use of struct keyword (instead of class) mean that it is meant to be used like C-style structs (POD)?

8
  • 9
    Getters and setters are non-idiomatic in any OO language. Apr 11, 2015 at 8:44
  • 3
    The only purpose to a getter and setter for a public field (or even a private field which is then effectively public) is that you can change them to do something else later. Other than that they are pointless Apr 11, 2015 at 12:14
  • 1
    @fredoverflow using 17 years old paper as an argument with strong qualifier "any" does not look like relevant up-to-date information to me. In some OO languages like C#, getters and setters are natural part of the language and their use is even encouraged by some best practices and coding guidelines - for some good reasons...
    – xmojmr
    Apr 11, 2015 at 14:06
  • 3
    @RichardTingle If you change the implementation of a setter later on, there is a high risk of silently breaking all your clients, because their assumptions about valid inputs may no longer hold. Apr 11, 2015 at 14:13
  • 1
    @RichardTingle that is only the case with physics engines that are designed to work that way.
    – user4595
    Apr 11, 2015 at 20:35

2 Answers 2

12

The Effective Go article on the official website mentions getters and setters are fine, and even has guidelines on how to name them:

Go doesn't provide automatic support for getters and setters. There's nothing wrong with providing getters and setters yourself, and it's often appropriate to do so, but it's neither idiomatic nor necessary to put Get into the getter's name. If you have a field called owner (lower case, unexported), the getter method should be called Owner (upper case, exported), not GetOwner. The use of upper-case names for export provides the hook to discriminate the field from the method. A setter function, if needed, will likely be called SetOwner. Both names read well in practice:

owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

Private fields and public getters are useful for guaranteeing invariants of objects since you can prevent people from poking the object's internals.

Since setters perform mutations, you should obviously be careful. Mutations don't play well with aliasing because a mutation in one place can effect code somewhere else, and this is especially important in concurrent settings which are widespread in Go.

Also, values are often implicitly copied in Go (similar to structs in C and C#), so a setter call that is expected to have an effect in some place may not have that effect, which is another reason to be careful when dealing with setters.

2
  • Thank you for your answer. But if you see the Go compiler's source, you can see in a lot of places like the AST, they have used public fields (starts with uppercase). If I write the same in Java, I have to write a lot of getters and setters. Note that an AST node's properties should be accessible from other parts like the parser or the code generator, so I have to write getters and setters for every field. But should I do the same in Go?
    – Fish
    Apr 12, 2015 at 4:28
  • 3
    @Fish AST nodes are just dumb data holders; their internal structure never changes. Therefore it's totally safe to make the fields public.
    – user4595
    Apr 12, 2015 at 11:00
1

As rightfold pointed out Effective Go already shows use of setters and getters. However it may not be clear when to use setters and getters if one comes from a Java background where setters and getters are used excessively almost as in iron rule.

However Go basically follows a pragmatic approach of keeping things simple when possible, avoiding over-engineering. I have articulated many of the same points about software development in general in this story going into more details about why you should avoid setters and getters and when you can use them.

But here are some questions you can ask yourself:

  1. Am I working on a simple concrete data type like a Point or Person? In this case just make fields public.

  2. If your type is part of an abstraction, where you will use types interchangeable through interfaces and you need to access some of the fields, then use setters and getters.

Basically the Go way is to not try to overthink and over-engineer stuff. Keep things as simple as possible. Use concrete types until that doesn't work. If it is obvious that you need an abstraction, then use design for that. But you see in the Java world reams of Setters and Getters are written for entirely dumb object that will never change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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