With structs, we can define properties we want a concept to have, like for example a car: An interface is meant to communicate something different, a behaviour. Den torsdagen den 26:e december 2013 kl. So, looking at our run() method: shouldnt this work? What would be the harm in also doing so in operator expressions and assignments? To describe what an interface is, lets start by talking about structs and how they are different from an interface. Yes, a "behavior" can be that there is some associated data like the Header(), but not only would adding "fields" to interfaces break the behavioral nature of interfaces (and be very difficult to implement; the compiler would almost have to generate its own accessors and stick them in the vtable) but it would only work for struct-backed concrete values. It feels bad having two ways to set/get a field: // Which do I use? Thats great for being sent to the printArea() method. Another neat trick really used is like: func (f F) foo() {} // yes, functions (fn types) can have methods! Anyway, if anyone else find this idea useful, please chime in. It seem that what you want is some kind of abstract class, in general is inheritance that Go don't have, then you want a new feature to fill the old missing one. Of course, more magic might reduce readability. Running this code, it returns 0. So far, a Rectangle or Square implements the Shape interface. You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group. It's just a syntactic sugar the way embedding is. They may have specific logic for their type. At this point, you are ready to create an instance and call both properties and methods (its new behaviour): Great, our Rectangle type has both the properties x and y as well as the behaviour from Shape. i have always found not having fields in interfaces strange, i posted about it a long time ago. Interfaces are about behaviors, not about data. I frequently use empty- or basic-type-backed types on which I can define methods to satisfy interfaces, especially in tests, and this would make that impossible. But I also think it wouldn't be going too far to propose that Go automatically dereference pointers in appropriate contexts. I'm pretty sure you can approach your problem differently by thinking about behavior rather than data. This "Sold" is just wrong from a modeling perspective. see. Thanks, you made me learn a new word :-), but still I don't know what you mean with "orthogonal" in this context. The sort package with its interface is as it should be, it's not a use case for interfaces with fields. Lets look at the first method area(): It looks like a regular function but theres this (r Rectangle) right before the function name. Anyway I have absolutely no problem with interfaces and methods. I also agree on that interface is perfect for the behavioral methods such as swap in the sort package, my point is that somewhere you need to get/set your data and fields in interface would be better then getter/setter. While having fields in an interface may seem convenient to you as a programmer it doesn't really fit with the concept of interfaces. If it is defined with fields then only structs can satisfy it obviously, but if there are only methods in the interface then any type could satisfy it. On the contrary, as mentioned in the previous posts in this discussion this is not a critical issue or a show stopper of any kind as there is already workarounds. On Friday, December 27, 2013 11:27:14 PM UTC+2, Peter Nguyen wrote: Yes, it is more coupled with the common struct. Let me start by saying that I understand where interfaces come from (what they are good for in OOP) and how they are very different in Go. Ok, so weve fully implemented an interface, what does it allow me to do? Well, no, because you are not changing the instance. You don't ask the object for data and act on it, you tell the object to act on it. Otherwise, I'm sure there are more important issues in Go to be dealt with first. It can satisfy multiple contracts that are overlapping, so advantages with interfaces also apply here. Now that weve described how an interface differs from a struct, lets talk about the motivation for using an interface. It could easily be an slice or a linked list or anything you want. Wouldn't it make sense to allow a interface to also define fields that a type has to have in order to implement the interface? It already does so on method invocations. fmt.Println("Hello, playground") I coin for the term "struct contract" :-), No, it's not the intention to break the interface model.
Since the call is being made on an interface, I feel like the inlining can't happen. If following your argument, then exported fields wouldn't be allowed and you only have getters/setters for everything which is not the case currently. 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. Which is 3x the typing, and reminds me of header files in C/C++. PS: This question appliesonlyfor user types defined with an underlying struct type I guess. // but we still have to get to all the other fields to do this: db.Exec("INSERT INTO foo (created, some_other_field) VALUES ($1, $2)", object.Created, object.SomeOtherField), https://groups.google.com/d/topic/golang-nuts/ZJ5DEv_36S8/unsubscribe, https://docs.google.com/document/d/1s6MxBsLyBG45SRS60a-aM01DmZ4hD1nMzGAKdTopKGY/edit.
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. The output from running the program should be: // shape.x undefined (type Shape has no field or method x). 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? Anyway, those are my thoughts. An example is structs created from JSON data that you want to persist in a db. Allowing properties would in effect narrow usability of some interfaces to struct{} only types (or pointers to such types). Yes, that's how I currently work around it too, but it has 2 issues: 1. 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. In another thread, Rob just described how to wrap a type that has the method you need, but with the wrong name to satisfy an interface. Sorry for bringing up an old thread but where can I find the other discussion about this? A non-struct type can still have "accessor" methods, and thus is able to satisfy all possible interfaces that can exist now. Because of this, it can't be considered a feature that benefits struct use, but rather, it's just a feature that limits the usefulness of non-struct types. Orthogonality, when used in Go related discussions, means features which work well together but don't overlap with each other (so that there won't be multiple redundant ways to accomplish the same task). A slight alteration to the run() method, with *: and your code now does what its supposed to. These solves your problem, and without too much hassle. 2. For me it would be acceptable that only struct types can satisfy an interface with fields. We can use something called type assertion like so: Ok, that works, so . That or I have to do some silly nonsense about encouraging people to call my UpdateHeader method before reading from Header. what i think is happening, that makes this strange for me, is that when you get familiar with thinking 'functionally', and realise that returning a value is just as much a behaviour as any other, the idea of separation between state and behaviour becomes unnecessary, and just seems cumbersome. It only make sense if the field is unexported.
Getters and setters are pointless on exported fields and just add noise and ambiguity to both code and documentation. (
OK, got you.
It says tells you that you can perform certain operations on a value and that those operations will obey certain properties that are set out in the interface definition. Would be a pity to lose such nice things ;-). What if I have data that relies on the Header? Presumably Foo and Bar have additional properties that aren't shared, and you would want to access them in your Insert method so that you could insert them into the the database. So Rob's solution to wrap a type would still work as well with normal interfaces. One nice side effect is that slice range loops could provide a mutable slice element. Because it means that your functions/methods can accept an object that satisfy an interface so that it has the required fields to be manipulated: Notice the ambiguity with getters/setters because in another function somewhere else you can do this instead: As Go's interface concept is not like any other languages, it shouldn't be too shocking to include such a feature. This proposal is not orthogonal to other aspects of the language. When using interface, you want something that can *do* something, hiding away the internals. I think you're missing the point about the database. Making the field private just forces the getter/setter methods to be created for each field you want to export and be able to access/modify. Theres also a second implementation for location(). This is of course not the traditional term of "interface" as you mentioned and maybe not calling it interface would perhaps be better. This chapter covers what an interface is and what to use it for. What if we want to change data, can we do that? What I'm trying to say that you are building poor models and because of that you have problems expressing the code. If you define an interface without fields, it should still be satisfiable by non-structs, If there is anambiguity it must because you already have an idea that. More than one type can implement the same interface. Pass an interface. With your proposal, yes, this would allow interfaces to specify struct fields that must be present, but the negative consequence is that when the feature is abused (and it will *always* be abused), third party libraries will be filled with senseless interface definitions that can only be implemented by strongly coupled structs.
I was assisted on #go-nuts with the following solution which is exactly what I needed, so hopefully it helps somebody else: So essentially it's tearing out the embedded Foo bits and passing it on to the function. Fields are data, not behaviour. It servers purely as an accessor. Maybe you want to keep your code DRYbut you're trying too much in this case! For that, you need to send a reference. I feel that you're figthing with the language. I just lost that option, because now if something could prompt a change, I *must* update the filed *immediately*. So the current model still applies. How am I going to update it when it's written to? There is no ambiguity in "t.Id() += 3" because Go doesn't support pointer arithmetic.
It's a case for refactoring and it's nothing wrong with that. There is no clear choice. Weve said for shape and shape2 to be of type Shape. I've already provided a use case in the previous posts and if it is not something that you run into in your code then you'll probably won't find this idea useful. swap) instead of asking for the data and swapping the data itself. (interface { Created time.Time }). Anyway, this is getting off-topic. To me, "read/write access to a field of some type" is a part of possible behaviors. I just don't understand, what is your problem withinterfaces and methods. And exactly because Go interfaces break the traditional notion of interfaces, wouldn't it be acceptable and even practical to allow them to have fields? That difference is crucial for making de-coupled systems and really harvesting the benefits of interface use. What if we need to access a Rectangle property on shape, can we? I just want to say +1. I would really like to read the opinion of one of the core developers, if any happened to stumble upon this thread. One of the main ideas of interfaces is to promote less coupling and it does that buy creating behavior dependencies vs structural dependency. The sort package requires an interface which is used to *tell* the object to do something (i.e. all that having fields separated from methods means, is that you force that there can not be any side-effects when you get or set them, but that seems like its leaking the implementation to me. Instead of describing the car itself, as a struct does, it describes what a car can do. Unnecessary bookkeeping when assigning data to the structs, instead of: Why specific fields for different struct is that they are of different data models. I agree, but also think that it is important not to discard new ideas and suggestions as there will be no improvement if everybody was just content with the way it is. What do you mean with "there are more important issues in Go to be dealt with first." With a .Header() method I can programmatically fill a header struct and send it to the requesting method. I think the 3rd way you mention is worthy of a bit more consideration. On Thu, 26 Dec 2013 11:28:41 PST Rob Pike <. It's irrelevant though for struct contracts. can have methods attached in Go due to the no-data rule of interfaces in Go. I can wrap my internalheader in a mutex, or some channeled request manager if race conditions become a problem. E.g: When you pass them to a method and you may want for example to set the field Created = time.Now() before the data is persisted, you have to define an interface with a setter for it to work currently. An Item may have SKU and a Service maybe needs start and end dates etc. Lets try: Ok, not working, we need to find a way to reach the underlying fields. ? I see those types coming and going, and probably a string would even suit better than an int. If you want a function that accepts a struct with particular fields, why not just make it accept a struct with those fields? It's not that it's more, it just doesn't make sense to have a setter/getter for an exported field as you then introduce ambiguity when you allow multiple ways to access that field. In fact, I think Go's interface implementation is great. Anyway, I also like the idea of having interfaces that define fields because it will effectively eliminate many use cases for generics and the reflect package. Fields are internal state of the object and it exposes too much of how the implementation is built, even getters and setters IMO are not good on interfaces, cause they also leak the internal structure information. I think using a "guaranteed data field" would be a bit of a nightmare and would promote inflexible implementations. This struct contract is not orthogonal to interfaces, thus I think is a bad candidate for language extension. It probably won't get you to where you're trying to go, but you can share fields by embedding structs: Embedding won't do as you still can't assert that the outer struct is the same as the embedded struct: The database case is for example data structs that has common fields such as Id, Created, Updated, Deleted, Active. It's the contract part that makes it interesting to include fields to an interface. The best solution I've found so far is to have a ModifyId() *Id field that returns a pointer, in order to cut down from 2 methods (get/set) to one. Although, yes, when such situation arises it would be convenient to express it that way but the problem is in the initial model, not the language. b := &B{} 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. By implementing both these methods, Rectangle has now fully implemented the Shape interface. If fields were allowed in interfaces, only structs could satisfy them. A good example is the sort package. I think you miss the point, this is not a discussion about getters/setters versus setting values directly on exported fields, as the decision has already been made and Go support exported fields. It gives me flexibility as a designer and yet the outward facing data to you is the same. ========, You do not have permission to delete messages in this group, Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message. That is, have the accessor method return a pointer: The need to dereference is slightly annoying, but not a big deal. On Wed, May 9, 2012 at 10:19 PM, tomwilde, I think you have actually just found the answer by yourself. For any Go feature being proposed, it must be considered whether it will produce any negative consequences; if so, those negative consequences should be considered much more strongly than any positive consequences, in order to keep the language clean and small. But that logic won't be called when you use fields, instead of methods. Well yes, even more of a reason to allow fields in interfaces as it will decouple your dependencies as I see it. But then, you should of course change your field to be non-exported and only allow access through your Get/Set methods. The question is, why do each of the order lines have to be a different type? Unless you can provide a good example with an excellent model then you can argue about the necessity of such "contract"-s. I hate dredge up an old topic but I found this today while googling for my particular issue. a.Id = "Two" An idea would be to separate it from interface completely into its own concept as "struct contracts". Because, then you can't create functions that can accept structs of different types. Yup. Even with fields defined via an interface you would still have to use reflection or casting to get to those additional properties. Is it your responsibility to avoid concurrent modification problems? With a Header field things become dicier. Struct contracts is not supposed to replace interfaces Don't know why people have that misconception. If you really need to worry about the specifics of the type (i.e.