Hi, I am trying to come up with a general guideline about returning struct vs returning interface. I have used both approaches. Despite the common wisdom is to return struct, I believe that returning interface is generally superior to returning struct. Here are my arguments for returning interface:
First, you may not want your data type to be copied by value. The data type may contain mutexes, references to other data types, etc. If you are returning struct, you may need to put comments in your code to prevent people from copying your data type by value. Note that this isn't ideal because an implementation is supposed to be a black box and the user should not need to know whether there is a mutex, etc. inside the struct. //DO NOT COPY. I MEAN IT! type VolatileDataType struct{ mtx sync.RWMutex data map[string]OtherData //etc.. } With the above comment, while people may remember not to do this: myCopy := myVolatileDataType //myVolatileDataType is of type VolatileDataType It is harder to prevent people from doing these: func DoWork(data VolatileDataType){ //... } //or this func DoWork() VolatileDataType{ //... } //or this myChannel := make (chan VolatileDataType) If you are returning interface, you avoid all these complications in a somewhat simpler way: type VolatileDataType interface{ Clone() VolatileDataType //... } type volatileImpl struct{ mtx sync.RWMutex data map[string]OtherData //etc... } func NewVolatileDataType() VolatileDataType{ return &volatileImpl{ //etc... } } By returning interface, people can do all the followings without any problem. You are actually passing around references to the actual object, and you will have to explicitly call its copy method if you need a copy. myPtr := myVolatileDataType //in the case of passing the actual data type around //or myCopy := myVolatileDataType.Clone() //if the data type supports copying func DoWork(data VolatileDataType){ //... } func DoWork() VolatileDataType{ //... } myChannel := make (chan VolatileDataType) In the case where your data type can be safely passed around by value, it doesn't matter whether you return interface or struct. So there isn't a problem in returning interface. Second, returning interface removes the need for dereferencing your data type. It results in a cleaner syntax. It also allows better equality comparison. Structs that contains map, etc. needs deeper equality comparison. s1:= MethodStruct1() //func() MyStruct s2:= MethodStruct2() //func() *MyStruct if s1 != *s2{ //do something } i1:=MethodInterface1() //func() MyInterface i2:=MethodInterface2() //func() MyInterface if i1.Equal(i2){ //do something } Finally, even if you are returning interface, you can still accept a subset of its interface (per Go's wisdom of accepting small interface). type VolatileDataType interface{ String() string } func NewVolatileDataType() VolatileDataType{ //... } func Print(target Stringer){ //... } Print(NewVolatileDataType()) //still works fine. I wonder whether it is correct to conclude that in general people should return an interface, unless there is a real reason not to. Or better is "to accept and return interfaces". Let me know what your experiences are regarding this matter. Thanks. Henry -- 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.