Alternative to Getters and Setters

1,711 views
Skip to first unread message

Rob Thornton

unread,
Nov 5, 2011, 12:13:41 AM11/5/11
to golang-nuts
This might be a silly topic but I'm curious to know the general
opinion of using getters and setters in Go. Effective Go seems to
acknowledge their necessity but discourage their use if possible (my
interpretation): http://golang.org/doc/effective_go.html#Getters

Is it better, meaning both more logical and more idiomatic Go, to use
a single unified function or two seperate get/set functions? To
illustrate:

// unified approach; assumes only single argument
func MyFunction(args ...int) int {
switch len(args) {
case 0: // getter
case 1: // setter
default: // handle invalid argument count
}

MyFunction() // getter
MyFunction(1) // setter

vs.

MyFunction() // getter
SetMyFunction(1) // setter

I, personally, rather like the unified method but I'm curious to know
how the approach would be received by other programmers.

John Asmuth

unread,
Nov 5, 2011, 12:26:39 AM11/5/11
to golan...@googlegroups.com
I feel like the "unified" function with the variadic parameter is a bad idea. What does it mean when someone calls MyFunction(1,2,3)? These are things that are best caught at compile time.

If you must use functions, use two of them.

Rodrigo Moraes

unread,
Nov 5, 2011, 2:48:28 AM11/5/11
to golang-nuts
On Nov 5, 2:26 am, John Asmuth wrote:
> I feel like the "unified" function with the variadic parameter is a bad
> idea. What does it mean when someone calls MyFunction(1,2,3)? These are
> things that are best caught at compile time.

I agree. Explicit is better. Also you would have to panic in that
function and you want to avoid having to handle that -- that would
require you more typing in the long run. :)

-- rodrigo

unread,
Nov 5, 2011, 9:03:58 AM11/5/11
to golang-nuts
I am not sure I understand the situation in which you want to use
getters/setters. Could you describe it with a few sentences?

Rob Thornton

unread,
Nov 5, 2011, 4:29:17 PM11/5/11
to golang-nuts
To John:

I have to agree with you there. I compile time check is much preferred
to a run-time check.

To Rodrigo:

I don't think a panic() is necessary. There are other ways to handle
the extra arguments as illustrated in my response below.

To anonymous:

Let's use a hypothetical scenario. An object 'Foo' has a property
called 'name'. I need to be able to retrieve the object's name and set
a new one after it has been instantiated. Too protect the object's
integrity I can't access its internal private variables, only it's
public members:

struct Foo {
name string
}

// setter function
func (f *Foo) SetName(name string) {
f.name = name
}

// getter function
func (f* Foo) Name() string {
return f.name
}

// unified getter/setter
func (f *Foo) Name(name ...string) string, os.Error {
switch len(name) {
case 0:
return f.name, nil
case 1:
f.name = name[0]
return nil, nil
default: // invalid argument count
return os.NewError(fmt.Sprintf("Invalid argument count. Expected
1, got %d.", len(name))
}

// a slightly different implementation of the unified approach
func (f *Foo) Name2(name ...string) string {
x := len(name)
switch {
if !x {
return f.name
}
f.name = name[0] // discard/ignore any additional arguments
}

Does that help illustrate my question? I want to know which approach
is better in Go. I think the answer is two separate functions due to
the compile-time checking as John points out. Though, I do like only
having one function to do everything.

My favorite thing about Go is that there are many ways to accomplish
the same task easily.

Rob

Rodrigo Moraes

unread,
Nov 5, 2011, 5:18:50 PM11/5/11
to golang-nuts
On Nov 5, 6:29 pm, Rob Thornton wrote:
> I don't think a panic() is necessary. There are other ways to handle
> the extra arguments as illustrated in my response below.

When the function receives a weird number of arguments, you have to
decide between: a) panic b) return an error c) behave arbitrarily.
your "default" behavior is option c, which can be perfectly fine for
your use, but can't be pointed as a generic solution.

-- rodrigo

Rodrigo Moraes

unread,
Nov 5, 2011, 5:20:56 PM11/5/11
to golang-nuts
On Nov 5, 7:18 pm, Rodrigo Moraes wrote:
> When the function receives a weird number of arguments, you have to
> decide between: a) panic b) return an error c) behave arbitrarily.

Meh. Please ignore this.

-- rodrigo

Anschel Schaffer-Cohen

unread,
Nov 5, 2011, 6:24:41 PM11/5/11
to golan...@googlegroups.com
Two points: first, this Name2 function does not actually compile, since it has no return value when multiple arguments are passed and it tries to treat an int (x) as a bool (!x). Second, this is a very silly example of why getters/setters might be useful; if you want other packages to be able to read and modify f.name, just export it in the first place. Setters are only useful when the action is more complicated then just changing a struct value.

Lars Pensjö

unread,
Nov 5, 2011, 7:58:22 PM11/5/11
to golan...@googlegroups.com
On Saturday, 5 November 2011 21:29:17 UTC+1, Rob Thornton wrote:
My favorite thing about Go is that there are many ways to accomplish
the same task easily.

Funny, I see it the other way around. The good thing about Go is that there are not so many ways to do a thing, And if there are, then there is usually an idiomatic way that is recommended. Compare with C++, where it sometimes takes an expert to understand the subtle difference of doing a task in different was.
 

Lars Pensjö

unread,
Nov 5, 2011, 8:10:11 PM11/5/11
to golan...@googlegroups.com
On Saturday, 5 November 2011 05:13:41 UTC+1, Rob Thornton wrote:
This might be a silly topic but I'm curious to know the general
opinion of using getters and setters in Go.

When I find I need a getter and a setter, I am usually creating a bad design. If an object is used for data storage, I don't take advantage of "the full power" of object orientation. If you need a value (from outside) that was defined with a setter, you need it for a purpose. I try to build that purpose into a member function of the object instead.

There was a proposal to actually export the parameter from the object instead of using a getter/setter. The drawback with that solution is that it makes the design less flexible. If you later on find that you need to change the representation of the local data, all source code using this value has to be changed.

In my opinion, keeping the design of the software flexible is a key success factor. Using a getter+setter impose a restriction on the design.You must for ever be able to recreate the original data.

Rob Thornton

unread,
Nov 6, 2011, 1:59:24 AM11/6/11
to golang-nuts
Lars

I have to agree with you that I typically try to avoid using getters
and setters in my own code. However, I should have been more clear in
my original post that I am implementing a C library with cgo which, in
typical C fashion, uses getters and setters. I want to provide a very
natural feeling Go interface. To date I have stuck with mirroring the
original library as close as possible just as most language bindings
(Russ' sqlite3 library, gogtk, etc) have done but I keeping wanting to
"pretty it up" if you will.
Reply all
Reply to author
Forward
0 new messages