PS: This question applies only for user types defined with an underlying struct type I guess.
getter and setter methods should be inlined, so there is no real
efficiency issue here.
--
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...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
The fact that you're exposing/requiring implementation structure to be of a type struct with a specific field definitely makes it *more* coupled. When working with Interfaces you don't want to assume anything about the implementation which is why using reflection to access internal fields depending on the type pretty much throws away the real benefits of interface as well.
I think what is missing for you is a behavior oriented approach when dealing with interfaces, along the lines of the "Tell, don't ask" idea. You don't ask the object for data and act on it, you tell the object to act on it. It enforces better encapsulation which leads to better design. This way you end-up with smaller interfaces, less knowledge about internals of the implementations, which leads to more maintainable code and implementations that can evolve without breaking the rest of the app and with components that can be easily replaced/swapped by another one.A good example is the sort package. By requiring a Swap method, it's the implementation job to know how to swap values which not only allows to sort different values but also makes it not dependent on the underlying storage structure. It could easily be an slice or a linked list or anything you want.
Den torsdagen den 26:e december 2013 kl. 18:17:45 UTC+1 skrev Rodrigo Kochenburger:The fact that you're exposing/requiring implementation structure to be of a type struct with a specific field definitely makes it *more* coupled. When working with Interfaces you don't want to assume anything about the implementation which is why using reflection to access internal fields depending on the type pretty much throws away the real benefits of interface as well.Please clarify, I don't see how instead of requiring a concrete struct of specific type to require an interface with specific fields be more coupled.
I think what is missing for you is a behavior oriented approach when dealing with interfaces, along the lines of the "Tell, don't ask" idea. You don't ask the object for data and act on it, you tell the object to act on it. It enforces better encapsulation which leads to better design. This way you end-up with smaller interfaces, less knowledge about internals of the implementations, which leads to more maintainable code and implementations that can evolve without breaking the rest of the app and with components that can be easily replaced/swapped by another one.A good example is the sort package. By requiring a Swap method, it's the implementation job to know how to swap values which not only allows to sort different values but also makes it not dependent on the underlying storage structure. It could easily be an slice or a linked list or anything you want.The sort package with its interface is as it should be, it's not a use case for interfaces with fields. This proposal is not a "critical" one as you can already work around it with getters/setters but rather an improvement as you really want to skip the bookkeeping exactly like the case with embedding structs.
Den torsdagen den 26:e december 2013 kl. 18:17:45 UTC+1 skrev Rodrigo Kochenburger:The fact that you're exposing/requiring implementation structure to be of a type struct with a specific field definitely makes it *more* coupled. When working with Interfaces you don't want to assume anything about the implementation which is why using reflection to access internal fields depending on the type pretty much throws away the real benefits of interface as well.Please clarify, I don't see how instead of requiring a concrete struct of specific type to require an interface with specific fields be more coupled.What I'm saying is that requiring an interface with specific fields will be more coupled than requiring an interface only with methods, because instead of only depending on behavior you're depending on a specific structure/datatype, which invalidates the benefits of using interfaces in the first place.
I think what is missing for you is a behavior oriented approach when dealing with interfaces, along the lines of the "Tell, don't ask" idea. You don't ask the object for data and act on it, you tell the object to act on it. It enforces better encapsulation which leads to better design. This way you end-up with smaller interfaces, less knowledge about internals of the implementations, which leads to more maintainable code and implementations that can evolve without breaking the rest of the app and with components that can be easily replaced/swapped by another one.A good example is the sort package. By requiring a Swap method, it's the implementation job to know how to swap values which not only allows to sort different values but also makes it not dependent on the underlying storage structure. It could easily be an slice or a linked list or anything you want.The sort package with its interface is as it should be, it's not a use case for interfaces with fields. This proposal is not a "critical" one as you can already work around it with getters/setters but rather an improvement as you really want to skip the bookkeeping exactly like the case with embedding structs.The sort package requires an interface which is used to *tell* the object to do something (i.e. swap) instead of asking for the data and swapping the data itself. That difference is crucial for making de-coupled systems and really harvesting the benefits of interface use. I'm pretty sure you can approach your problem differently by thinking about behavior rather than data.If you really need to worry about the specifics of the type (i.e. the fields) then you're better off using the concrete type rather than an interface type.Anyway, this is getting off-topic. I'm explaining why interfaces does not have fields: it describes how objects interact with each other, it does not describe how the object expose internal data. That said, I would not expect fields to ever be added to an interface because it goes against a lot of the benefits of why one would use interface, goes against what the term "Interface" means (traditionally), I believe there are some internal implementation details that would make this hard to implement and it would potentially break the Go1 API stability promise (http://golang.org/doc/go1compat).
--
func (this A) Foo() {}b.Foo()Does work though.
I agree that it won't work in the database case, but my point was the suggested change won't fix that problem. As long as any fields are different between two structs you'd have to pass in interface{} anyway.
x.Created = time.Now()if ok {x, ok := o.(interface { Created time.Time })I suppose you'd be able to cast easier:}
Is that what you were imagining? You can pull off a similar trick using embedding:
http://play.golang.org/p/Woz55L30N1
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/ZJ5DEv_36S8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
I think using a "guaranteed data field" would be a bit of a nightmare and would promote inflexible implementations. With a .Header() method I can programmatically fill a header struct and send it to the requesting method. I can wrap my internal header in a mutex, or some channeled request manager if race conditions become a problem. It gives me flexibility as a designer and yet the outward facing data to you is the same. With a Header field things become dicier. Is it your responsibility to avoid concurrent modification problems? What if I have data that relies on the Header? How am I going to update it when it's written to? What if I only want to spend the work assembling the header when it's explicitly requested, and save the effort of making it otherwise? I just lost that option, because now if something could prompt a change, I *must* update the filed *immediately*. That or I have to do some silly nonsense about encouraging people to call my UpdateHeader method before reading from Header.
Obviously having to use discretion isn't something that inherently disqualifies an idea, and sometimes an accessor is only conceivably ever going to be an accessor. But I feel like the "guaranteed field" idea is going to encourage bad design and hasty API rewrites when the developer realizes that they actually DO have to do extra work when setting a value, or protect itself from race conditions, or whatever else. I know I recently had a case where something I definitely would have initially suspected should be a freely exposed field suddenly needed to have a few lines added to the Get and Set methods to prevent problems.
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/ZJ5DEv_36S8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
That's an impressive list indeed.
Returning to the issue:
The only thing I want to say is that maybe it's better to just accept the language Go as it is right now.
When you are facing a problem, try to solve it with the tools you have and forget about the tools you get in other languages.
type Object interface {Created time.Time}func Insert(object Object) {object.Created = time.Now()}// Both Foo and Bar satisfy the struct contract of Object by having the field Created of type time.Timevar foo Foovar bar BarInsert(foo)Insert(bar)
I just don't understand, what is your problem withinterfaces and methods. These solves your problem, and without too much hassle.
This struct contract is not orthogonal to interfaces, thus I think is a bad candidate for language extension.
Yes, that's how I currently work around it too, but it has 2 issues:1. Tight coupling with the common struct. As with interfaces, a struct will implicit implements a contract just by having the defined fields. It can satisfy multiple contracts that are overlapping, so advantages with interfaces also apply here.
2. Unnecessary bookkeeping when assigning data to the structs, instead of:type Saleable contract {Name stringPrice floatVat floatSold bool
}
func PrintOrder(order []*Saleable) {for _, orderLine := range order {fmt.Println("Product: ", orderLine.Name)fmt.Sprintf("Sum: %f", orderLine.Price * (float(1) + orderLine.Vat))orderLine.Sold = true}}Why specific fields for different struct is that they are of different data models. They may have specific logic for their type. An Item may have SKU and a Service maybe needs start and end dates etc.
DoSomethingWithFoo(bar.Foo)
Yup. The complete source, btw (because it makes the point more clearly):
========
package main
import "fmt"
type A struct {
Id string
}
type B struct {
A
}
func main() {
fmt.Println("Hello, playground")
b := &B{}
b.Id = "One"
DoSomethingWithAnA(&b.A)
fmt.Println(b.Id)
}
func DoSomethingWithAnA(a *A) {
a.Id = "Two"
}
========
-jf