Thoughts: Treat function as a single-method interface{} if signatures match

1,021 views
Skip to first unread message

Ugorji Nwoke

unread,
Jun 1, 2012, 10:06:03 AM6/1/12
to golan...@googlegroups.com
I have places where I have defined something akin to http.HandlerFunc.

Scenario:
  type Handler interface {
    ServeHttp(ResponseWriter, *Request)
  }

  type HandlerFunc func(ResponseWriter, *Request)

  func (h HandlerFunc) ServeHttp(w ResponseWriter, r *Request) {
    h(w, r)
  }

  func routehttp(h http.Handler, w ResponseWriter, r *Request) {
    // ...
    h.ServeHTTP(w, r)
    // ...
  }

  func serveHomepage(w ResponseWriter, r *Request) {
    // ...
  }

  func serve(w ResponseWriter, r *Request) {
    // ...
    routehttp(HandlerFunc(serveHomepage), w, r)
  }

It will be nice to eliminate the HandlerFunc type completely and just pass serveHomepage into routehttp as a Handler. I see this as analogous to auto-converting a type to an interface (this is auto-converting a function to an interface).

It will make it easier to use functions where interfaces are expected without creating boilerplate where the intent is already clear in the code.

Thoughts?

tomwilde

unread,
Jun 1, 2012, 10:28:39 AM6/1/12
to golan...@googlegroups.com
I suppose the thought behind this was that you could create an object with own methods and properties and make it a handler by giving it a ServeHTTP method.

I agree though, that in practice instantiating anything to use it just once feels wrong and hence a function as a single entry-point feels more natural. And that's probably why they created the HandlerFunc type.

Brad Fitzpatrick

unread,
Jun 1, 2012, 10:32:45 AM6/1/12
to Ugorji Nwoke, golan...@googlegroups.com
FWIW, I've often wanted this too.

Ugorji Nwoke

unread,
Jun 1, 2012, 10:33:59 AM6/1/12
to golan...@googlegroups.com
Thanks Tom.

I just re-read my post, and it wasn't clear. My point is not about Handler and HandlerFunc (I just used that to illustrate).

My question is really about allowing functions to be passed as single-method interfaces where the signatures match, so users and libraries do not have create wrapper interfaces (like http.HandlerFunc) and create extra functions which take the wrapper interface (like http.HandleFunc).

And my skewed reasoning is that it is analogous to auto-converting a value to an interface.

Ugorji Nwoke

unread,
Jun 1, 2012, 10:38:24 AM6/1/12
to golan...@googlegroups.com, Ugorji Nwoke
Thanks Brad.

This and passing methods as functions will help reduce the creation of pass-through wrappers/closures a fair amount. i.e.

On Friday, June 1, 2012 10:32:45 AM UTC-4, Brad Fitzpatrick wrote:
FWIW, I've often wanted this too.

Message has been deleted

Ugorji Nwoke

unread,
Jun 1, 2012, 10:47:09 AM6/1/12
to golan...@googlegroups.com
I think this one would carry its weight. It reduces boilerplate (wrappers), feels idiomatic (like type inference, auto-convert to interface), and is easy to explain/understand, makes library API's easier (without library authors having to decide whether to add XXXFunc type in addition to XXX interface), etc.

MHO.


On Friday, June 1, 2012 10:38:59 AM UTC-4, Peter Thrun wrote:
My question is really about allowing functions to be passed as single-method interfaces where the signatures match, so users and libraries do not have create wrapper interfaces (like http.HandlerFunc) and create extra functions which take the wrapper interface (like http.HandleFunc).

I have also wanted this feature, but I wonder if the extra feature pulls its weight.  There's a cost to adding the feature to the language.  It's another thing for people to learn. It's not all that onerous to define and use a wrapper interface.
Message has been deleted

Ugorji Nwoke

unread,
Jun 1, 2012, 11:43:03 AM6/1/12
to golan...@googlegroups.com
I think they are orthogonal features, that combined together will become very powerful.

currying the receiver allows us pass v.Method as a function value.
This proposal allows us pass function value as a single-abstract-method interface. 
Both can be combined e.g. to pass any method as the value of a single-abstract-method interface (so long as their signatures match, which is what interfaces do).

To illustrate:

type myinterface interface {
  mymethod() error
}

type mystruct struct { }
func (m mystruct) something() error { return nil }

func callmyinterface(x myinterface) error {
  return x.mymethod()
}

func main() {
  h := mystruct{}
  callmyinterface(h.something) // currying something method as a function, which is then passed as a myinterface into callmyinterface.
}

It makes interfaces much more powerful, allowing more powerful refactoring, etc (... all those wonderful benefits of Go interfaces).

On Friday, June 1, 2012 11:05:35 AM UTC-4, Peter Thrun wrote:
What if the language supported currying the receiver in a value.Method expression?   With this feature, APIs can be designed to use functions instead of single method interfaces. 

André Moraes

unread,
Jun 1, 2012, 11:46:55 AM6/1/12
to Peter Thrun, golan...@googlegroups.com
On Fri, Jun 1, 2012 at 12:05 PM, Peter Thrun <peter...@ymail.com> wrote:
> What if the language supported currying the receiver in a value.Method
> expression?   With this feature, APIs can be designed to use functions
> instead of single method interfaces.

Single method interfaces add a great value to the language. Define
function types shouldn't replace single method interfaces.

Also, what you want is already possible (to some cases) but using custom types:

type MyFnType func(int,int) int
func DoMyFn (fn MyFnType) { fn(0,0) }


--
André Moraes
http://amoraes.info

André Moraes

unread,
Jun 1, 2012, 1:46:14 PM6/1/12
to sdeg...@8thlight.com, golan...@googlegroups.com, Peter Thrun
> This doesn't help when we don't have control over the interfaces, which is
> by far the most common case. In this event, we still have to create an
> adapter type solely for the purpose of passing a function where it already
> matches by signature.

I agree that making the compiler understand that a function value
implements a interface is useful and I hope that this goes into the
language. This change shouldn't break any Go1 code.

But my comment was referring to this:

> What if the language supported currying the receiver in a value.Method expression?
> With this feature, APIs can be designed to use functions instead of single method interfaces.

Rob 'Commander' Pike

unread,
Jun 1, 2012, 1:59:24 PM6/1/12
to André Moraes, sdeg...@8thlight.com, golan...@googlegroups.com, Peter Thrun
I'm against this idea. A function is not a method and conflating the
ideas saves a trivial amount of code at the cost of potentially
dangerous and confusing non-orthogonality. This proposal is similar
to the claim that

struct { int }

and

int

should be assignable to each other. While I can see operational and
convenience arguments why that could be true, it breaks the model on
which the language is built.

Go is not this kind of language.

-rob

Ugorji Nwoke

unread,
Jun 1, 2012, 2:14:20 PM6/1/12
to golan...@googlegroups.com, André Moraes, sdeg...@8thlight.com, Peter Thrun


On Friday, June 1, 2012 1:59:24 PM UTC-4, r wrote:
I'm against this idea. A function is not a method and conflating the
ideas saves a trivial amount of code at the cost of potentially
dangerous and confusing non-orthogonality.  This proposal is similar
to the claim that

  struct { int }

and

  int

should be assignable to each other.
I think it's more like:
// currently supported
var b *bytes.Buffer = new(bytes.Buffer)
var s fmt.Stringer = b // auto assign a *bytes.Buffer value to a fmt.Stringer

// extending idea to proposal (although admitted not as straightforward)
func PrintName() string { return "name" }
var s fmt.Stringer = PrintName // auto assign a func() string value to a fmt.Stringer (which is a single-method-interface containing only func() string)
 
While I can see operational and
convenience arguments why that could be true, it breaks the model on
which the language is built.

I appreciate your response, Rob. I appreciate that you guys have a more holistic and complete view of the whole language, so I'm comfortable with whatever decisions you guys make. I just wanted to put this on the radar; whatever comes out of it. Combined with currying the receiver in a method, it's pretty powerful IMO.

Rob 'Commander' Pike

unread,
Jun 1, 2012, 2:50:32 PM6/1/12
to Ugorji Nwoke, golan...@googlegroups.com, André Moraes, sdeg...@8thlight.com, Peter Thrun
On Fri, Jun 1, 2012 at 11:14 AM, Ugorji Nwoke <ugo...@gmail.com> wrote:
>
>
> On Friday, June 1, 2012 1:59:24 PM UTC-4, r wrote:
>>
>> I'm against this idea. A function is not a method and conflating the
>> ideas saves a trivial amount of code at the cost of potentially
>> dangerous and confusing non-orthogonality.  This proposal is similar
>> to the claim that
>>
>>   struct { int }
>>
>> and
>>
>>   int
>>
>> should be assignable to each other.
>
> I think it's more like:
> // currently supported
> var b *bytes.Buffer = new(bytes.Buffer)
> var s fmt.Stringer = b // auto assign a *bytes.Buffer value to a
> fmt.Stringer

No it's not. Promoting a function to a method requires a change of
representation and implementation. A function does not implement an
interface because an interface is implemented by methods, not
functions. Your request to hide the distinction is, in my view,
analogous to ignoring the difference between an int and a struct with
one int field: you're ignoring the wrapper and what it represents.

When you assign a value of type *bytes.Buffer to a variable of type
fmt.Stringer, the language lets you elide the type assertion for
convenience, but the language *could* require you to write var s
fmt.Stringer = b.(fmt.Stringer). It doesn't because that type
assertion can be statically determined. (And in cases where it can't
be statically determined, Go makes you write the assertion.)

On the other hand, there is no such trivial mechanism X to write var s
fmt.Stringer = X(PrintName); it's not an elemental language operation.
To do this assignment, it's necessary to construct an interface type
and an implementation of that type. You say to do that for you would
be nice, and perhaps it would, but I stress it's quite a different
level of operation from merely eliding an explicit type check that can
be done statically anyway.

Again, Go is not this kind of language.

-rob

Ugorji Nwoke

unread,
Jun 1, 2012, 3:06:39 PM6/1/12
to golan...@googlegroups.com, Ugorji Nwoke, André Moraes, sdeg...@8thlight.com, Peter Thrun
Well explained; the difference is clear. The convenience of the feature is clear too,
but I understand the reservations to what is tantamount to auto-generating an interface wrapper.

Thanks.

roger peppe

unread,
Jun 1, 2012, 3:23:31 PM6/1/12
to golang-nuts


darn, forgot to reply-all

---------- Forwarded message ----------
From: "roger peppe" <rogp...@gmail.com>
Date: Jun 1, 2012 7:34 PM
Subject: Re: [go-nuts] Re: Thoughts: Treat function as a single-method interface{} if signatures match
To: "Ugorji Nwoke" <ugo...@gmail.com>

I'm with rob, although I've thought on this idea a few times,
slightly wistfully.

It would be confusing for programs that reflect - what would would
the type of the underlying value inside the interface have,
and would it have any methods?

If the underlying type is exactly the original function type (and
I think it would be very confusing if this was *not* the
case) then this code would break, because when it's not in
an interface, the underlying value has no methods:

type X interface{ F func() }
var x X = func(){}         // x has method X
y := reflect.ValueOf(x)
y.MethodByName("F").Call()

I suppose an alternative would be to say that
a function had an infinite number of methods
with all possible names, each with the same type
signature, but that's just getting silly.

Robert Johnstone

unread,
Jun 1, 2012, 3:55:02 PM6/1/12
to golan...@googlegroups.com
Thanks.  I was having trouble following Rob's comments.  This concrete example made it clear.

si guy

unread,
Jun 1, 2012, 8:09:19 PM6/1/12
to golan...@googlegroups.com
This would IMO significantly raise the barriers for entry to go. Interfaces were definitely the hardest part (for me at least) of go syntax to grok, please don't make it harder. It may be orthogonal (I'm not sure I know what that means anymore) but it is damn confusing to read in one pass because it disguises function signatures in the call, or at least appears to.

Ugorji Nwoke

unread,
Jun 1, 2012, 8:18:37 PM6/1/12
to golan...@googlegroups.com


On Friday, June 1, 2012 8:09:19 PM UTC-4, si guy wrote:
This would IMO significantly raise the barriers for entry to go. Interfaces were definitely the hardest part (for me at least) of go syntax to grok, please don't make it harder. It may be orthogonal (I'm not sure I know what that means anymore) but it is damn confusing to read in one pass because it disguises function signatures in the call, or at least appears to.
There "may" be some things that are arguably "hard" about Go. I don't think interfaces make that list (IMHO). 

Rob 'Commander' Pike

unread,
Jun 1, 2012, 8:33:19 PM6/1/12
to Ugorji Nwoke, golan...@googlegroups.com
Yeah, I agree. I don't see why they're hard. (You wrote "hardest part
of go syntax". Surely you didn't mean syntax.) They're trivial, at
least if you set aside the subtleties around interface satisfaction
with pointer vs. value receivers.

But others have found them baffling too. I can only guess that the
word "interface" has connotations from other languages that must be
forgotten before Go makes sense. For instance, I've talked to C++
programmers who saw "dynamic dispatch" and "interface" together and
immediately conflated "interface" and "class" and became utterly
confused.

But really, they're trivial. Here's a set of methods. Here's a type
that does/doesn't implement that set. Done.

If you can explain what's hard about them, I'd like to hear more.

-rob

Rémy Oudompheng

unread,
Jun 2, 2012, 5:52:00 AM6/2/12
to Brad Fitzpatrick, Ugorji Nwoke, golan...@googlegroups.com
On 2012/6/1 Brad Fitzpatrick <brad...@golang.org> wrote:
> FWIW, I've often wanted this too.

I'm not sure I've ever wanted this, and comments from Rob and roger
make me not want this, however, I have often wanted that a struct type
having a field of function type would automatically get the associated
method of the same name as the field.

That is, I have sometimes wanted to do:

type DynamicStringer struct {
String func() string
}

var _ fmt.Stringer = DynamicStringer{}

Rémy.

Job van der Zwan

unread,
Jun 2, 2012, 7:08:27 AM6/2/12
to golan...@googlegroups.com, Ugorji Nwoke
The hardest part of learning often unlearning what's been taught before. Maybe he mistook behaviour-defines-object (like a Go Interface) for the familiar object-defines-behaviour (like a C++ class)?

Ugorji Nwoke

unread,
Jun 2, 2012, 10:57:17 AM6/2/12
to golan...@googlegroups.com


On Friday, June 1, 2012 3:23:31 PM UTC-4, rog wrote:


darn, forgot to reply-all

---------- Forwarded message ----------
Date: Jun 1, 2012 7:34 PM
Subject: Re: [go-nuts] Re: Thoughts: Treat function as a single-method interface{} if signatures matchI'm with rob, although I've thought on this idea a few times,

slightly wistfully.

It would be confusing for programs that reflect - what would would
the type of the underlying value inside the interface have,
and would it have any methods?

If the underlying type is exactly the original function type (and
I think it would be very confusing if this was *not* the
case) then this code would break, because when it's not in
an interface, the underlying value has no methods:

type X interface{ F func() }
var x X = func(){}         // x has method X
y := reflect.ValueOf(x)
y.MethodByName("F").Call()

FWIW, this can just as easily be made to work ... if the idea of the the implementation is that the compiler does what is tantamount to auto-generating the interface wrapper behind the scenes.

type X interface { F() } // X is an single-abstract-method interface having a niladic function with no return values
var x X = func() {} // x is now "conceptually" a value of type _x_X (something auto-generated) whose signature is: type _x_X func(); func (v _x_X) F() { v() }
y := reflect.ValueOf(x) // y is a value of type _x_X
y.MethodByName("F").Call() // just works

The key part to me is what Rob said, twice: "Go is not this kind of language". 

This suggests to me that the Go authors have an "understandable" aversion to auto-generating things that don't fit cleanly. Thus,the delay/aversion to:
- Generics, 
- currying the receiver of a method to allow v.Method(...) be a func(...), 
- suggestions to reducing error handling verbosity ie repetitions of "if err != nil { return }" e.g. must(...), ^err (return if err is written to non-nil), etc.

I like (love) the convenience of these proposals, but I'm happy to let them worry about and figure out if/how this all would fit holistically into Go.

Ugorji Nwoke

unread,
Jun 2, 2012, 11:02:29 AM6/2/12
to golan...@googlegroups.com, Brad Fitzpatrick, Ugorji Nwoke
This would be pretty cool. It allows you replace the implementation of a function without having to create a wrapper. I've done this in my code where i have:
  var LogFn func(...)
  func Log() {
    if LogFn != nil { LogFn(...) }
  }
  
The only concern is that the variable can be nil (which kinda makes the wrapper function still necessary for callers).

Rémy.

Carlos Castillo

unread,
Jun 4, 2012, 4:26:44 PM6/4/12
to golan...@googlegroups.com
What happens when two interfaces used for different or opposite things could match a single promoted function?
io.Reader & io.Writer have the same interface if you ignore the method's name (which your suggestion would do).

ie:

func myReader (b []byte) (int,error) {
   ... // Do reading
}

The function above would match both an io.Reader & an io.Writer, even though it's implementation would only work properly for one of them. Also the compiler would have to consider your function against every interface that matches and generate code for all of them... ie in this case there are at least two interfaces (possibly more) which have a single method that takes a byte slice and returns an (int,error) pair.

So for the benefit of writing one line of code instead of two, we break type safety for interfaces, and generate a huge amount of wrapper code for every function which matches the signature of an interface with a single method.

Reinhard Wobst

unread,
Jun 5, 2012, 4:28:42 AM6/5/12
to golang-nuts
On 2 Jun., 13:08, Job van der Zwan <j.l.vanderz...@gmail.com> wrote:
> The hardest part of learning is often unlearning what's been taught before.

Wow, this becomes my next mail signature :-)

Reinhard

si guy

unread,
Jun 5, 2012, 6:17:27 AM6/5/12
to golan...@googlegroups.com
Sorry for the late reply (and the long post), but I wanted to think this through.

I mentioned that interfaces were the hardest part of the go syntax to grok, and I feel that I'm not the only one in this position.

It is not a matter of patterns learned in other languages as before go, I had almost never used "interfaces" or templates or other such structures. In fact most of the programming I've done in other languages resembles a sort of C, with or without OO depending on the language. (a note here, I also never liked type hierarchies and inheritance so I avoided them altogether, preferring closures where available)

That out of the way, I still feel that interfaces in go are "hard" for one major reason that you guys may have overlooked: they do not do what you might expect them to do, they do the opposite.

They are often described in the documentation as easing function design, with plenty of examples to support that, among other things. What is not often or clearly mentioned is that interfaces are not real, in the sense that they contain no programmer accessible (barring unsafe) data. They are not actually interfaces in the sense of the english word, they are archetype definitions. (I have trouble here describing them without using words that have meaning in other programming languages so bear with me). An interface type does not describe data at all, it describes the datas signature and therein lies the problem.

I can identify the moment that I actually understood what interfaces do: when somebody on the group pointed out that you cannot instantiate a variable of type interface and expect go to figure out what it should actually contain. This needs to be made _much_ clearer in the documentation.

For a long time I was living with the assumption that the compiler/runtime did a sort of magic trick, and that the underlying type of an interface was unknown until the method set had been winnowed down to one applicable type, and further that given a rigorous naming scheme this should be irrelevant and the runtime would just pick a valid type from a hat or something. Obviously this was wrong.

You asked for a clarification and that's the best I can come up with, hopefully it is helpful and as always thanks for listening, and for go.

-Simon Watt

Thomas Bushnell, BSG

unread,
Jun 5, 2012, 6:54:11 AM6/5/12
to si guy, golan...@googlegroups.com
On Tue, Jun 5, 2012 at 12:17 PM, si guy <sjw...@gmail.com> wrote:
That out of the way, I still feel that interfaces in go are "hard" for one major reason that you guys may have overlooked: they do not do what you might expect them to do, they do the opposite.

I think this depends much on where you come from. They do exactly what I expect, because I expect them to behave like what Smalltalk 80 called a "protocol": a standard set of methods that you can call on some objects, distinguished by name and calling signature, but not related to class. Because Smalltalk 80, like Python and Ruby, supports "duck typing", an interface is just a name for a group of message selectors.

Smalltalk, Python, and Ruby, however, do not have typed variables. So in those languages, protocols (or interfaces) are not ever declared to the system; they are just programming conventions and ways to organize code. But if you have typed variables--a key design decision in go--then you need to elevate interfaces to be actual types.

If you are used to thinking of types as descriptions of data, then it is very confusing that an interface does not describe any data. But in type theory, that's not what a type really is. A type defines a set of operations that can be performed on or with an object. Despite the name, "uint32" does not mean "an integer stored with thirty-two binary bits", it means "a member of the set Z32"; which is itself defined not as a particular representation, but as a meaning for operations like addition, multiplication, and so forth.

The great mistake (in my opinion) of object oriented languages is to think in terms of data definition. For Smalltalk this was always in the background, and the system actively encouraged you to think not in terms of data definition, but in terms of abstract object protocols (what Go calls interfaces). But in C++ and Java the world got turned around, and the key feature of duck typing was left aside, and the language suddenly forced you to think in terms of data definition. In C++ this was driven to insanity, with the need to define methods within a data definition construct!

So if you come from C++ and Java, you'll think of interfaces as being very confusing in this way, because Go interfaces are not like C++ or Java. They are much more like the informal protocol specifications that Smalltalk used, elevated to the level of formal types as is necessary in a language which has typed variables.

Thomas

Ugorji Nwoke

unread,
Jun 5, 2012, 7:30:57 AM6/5/12
to golan...@googlegroups.com, si guy
I agree with everything you said, except that Java actually prepares you well for understanding Go's interfaces. Go's interfaces are much like Java's, except you do not have to declare it. In java, an interface is a set of methods, and your "type/class" must "explicitly" declare that it implements that interface. 
i.e. Java code below:
public interface Predator {
       boolean chasePrey(Prey p);
       void eatPrey(Prey p);
}

public class Lion implements Predator { // In Go, you don't have to explicitly declare the interfaces you implement
        public boolean chasePrey(Prey p) {
               // programming to chase prey p (specifically for a lion)
        }
        public void eatPrey (Prey p) {
               // programming to eat prey p (specifically for a lion)
        }
}

In Go, you don't have to declare the interface you implement.


Thomas

Ian Lance Taylor

unread,
Jun 5, 2012, 10:02:09 AM6/5/12
to si guy, golan...@googlegroups.com
si guy <sjw...@gmail.com> writes:

> They are often described in the documentation as easing function
> design, with plenty of examples to support that, among other
> things. What is not often or clearly mentioned is that interfaces are
> not real, in the sense that they contain no programmer accessible
> (barring unsafe) data. They are not actually interfaces in the sense
> of the english word, they are archetype definitions. (I have trouble
> here describing them without using words that have meaning in other
> programming languages so bear with me). An interface type does not
> describe data at all, it describes the datas signature and therein
> lies the problem.

Interesting. Can you suggest a couple of sentences to add to Effective
Go to make this clearer?

I'm not sure I agree that interfaces are not real, but it's likely that
I misunderstand what you mean by that. I think I would say that a
variable of interface type is a copy of some non-interface value, but
you get a restricted view of that copy. It's only slightly like the
English word interface, but it's very much like the Java concept.

Ian

si guy

unread,
Jun 5, 2012, 11:43:14 AM6/5/12
to golan...@googlegroups.com, si guy
I would add something like this to the description (right before the para that starts " A type can implement multiple interfaces "):

"A type is said to implement an interface if it contains the method signatures listed in the interface definition. For example:"
(code example with an interface definition and two types with method sets, one that implements the interface and one that doesn't and comments describing why/why not)
"If a type implements an interface, then it can be passed wherever that interface is accepted, or assigned to a variable of that interface type."
(code example with an interface definition, a type that implements it, a function with interface input and a main() that calls that function and assigns to the interface type)
"Once a type is passed as or assigned to an interface value, it's member variables cannot be accessed, except through/after a type assertion(link)."
(the "A type can implement multiple interfaces" part goes after here)

The language and structure here may not be best, but I hope the intent of my suggestion is clear. The idea being to demonstrate how interfaces are not the same as values.

Thomas Bushnell, BSG

unread,
Jun 5, 2012, 11:50:59 AM6/5/12
to si guy, golan...@googlegroups.com
On Tue, Jun 5, 2012 at 5:43 PM, si guy <sjw...@gmail.com> wrote:
I would add something like this to the description (right before the para that starts " A type can implement multiple interfaces "):

"A type is said to implement an interface if it contains the method signatures listed in the interface definition. For example:"
(code example with an interface definition and two types with method sets, one that implements the interface and one that doesn't and comments describing why/why not)
"If a type implements an interface, then it can be passed wherever that interface is accepted, or assigned to a variable of that interface type."
(code example with an interface definition, a type that implements it, a function with interface input and a main() that calls that function and assigns to the interface type)
"Once a type is passed as or assigned to an interface value, it's member variables cannot be accessed, except through/after a type assertion(link)."
(the "A type can implement multiple interfaces" part goes after here)

The language and structure here may not be best, but I hope the intent of my suggestion is clear. The idea being to demonstrate how interfaces are not the same as values.

I like this, but I would take a slightly different tack.

You speak of "passing a type", which you can't actually do. You can only pass a value. (And, since interfaces are types, it doesn't make sense to pass them.)

So your second sentence could be "If a a type implements an interface, then an expression of that type can be passed wherever that interface is accepted, or assigned to a variable of that type."

The third I would rephrase even more dramatically. "If a type implements an interface, and an expression of that type is assigned to a variable of the interface type, the latter variable still has only the interface type; it does not acquire the additional characteristics of the type of the original expression."

The point here is that it is variables and expressions which are typed, and not values; types apply to lexical entities and only indirectly to dynamic ones.

So:

var a interface {...}
var b struct {...}
a = b

does not mean that "a" now has the type struct {...}.  "a" has the same type it always did: "interface {...}". Why? Because it's not values that are typed, it's lexical expressions. No matter what value is assigned, the type of the expression remains exactly what the program text says it is.

Thomas

Jan Mercl

unread,
Jun 5, 2012, 11:54:42 AM6/5/12
to si guy, golan...@googlegroups.com

Dne 5.6.2012 17:43 "si guy" <sjw...@gmail.com> napsal(a):


>
> I would add something like this to the description (right before the para that starts " A type can implement multiple interfaces "):
>
> "A type is said to implement an interface if it contains the method signatures listed in the interface definition. For example:"
> (code example with an interface definition and two types with method sets, one that implements the interface and one that doesn't and comments describing why/why not)
> "If a type implements an interface, then it can be passed wherever that interface is accepted, or assigned to a variable of that interface type."
> (code example with an interface definition, a type that implements it, a function with interface input and a main() that calls that function and assigns to the interface type)
> "Once a type is passed as or assigned to an interface value, it's member variables cannot be accessed, except through/after a type assertion(link)."
> (the "A type can implement multiple interfaces" part goes after here)
>
> The language and structure here may not be best, but I hope the intent of my suggestion is clear. The idea being to demonstrate how interfaces are not the same as values.

I don't like the idea of even mentioning type's field members.  Not every type has them and type's data (its value) is fuly orthogonal to an interface. Actually, that orthogonality is the very concept of an interface (in Go).

-j

si guy

unread,
Jun 5, 2012, 12:01:45 PM6/5/12
to golan...@googlegroups.com, si guy
The passing a type thing was due to a caffeine shortage.
Yes! Except that I would avoid the use of "expression" and go with variable instead, I know it's not totally correct, but it is easier to understand.


Tonic Artos

unread,
Jun 5, 2012, 4:51:16 PM6/5/12
to si guy, golan...@googlegroups.com

Isn't value already the accepted term in this case.

pphalen

unread,
Jun 5, 2012, 5:11:21 PM6/5/12
to golan...@googlegroups.com
si guy: When you say interfaces "are not real," and mention you have difficulty finding a more proper descriptive term, I think the word "abstract" is still apt.

In his book, _Programming in Go_, Mark Summerfield writes, "Interfaces are wholly abstract, so it is not possible to instantiate an interface. However, it is possible to create a variable whose type is that of an interface -- and which can then be assigned a value of any concrete type that has the medhods the interface requires."

Here, I think the term "wholly abstract" is evocative. What is perhaps missing from the go docs is a simple sentence or two providing the *motivation* for interfaces. Simply saying that go interfaces provide a sort of duck typing like Python won't be useful to every reader.

Rob 'Commander' Pike

unread,
Jun 5, 2012, 5:51:29 PM6/5/12
to pphalen, golan...@googlegroups.com
Interface types are wholly abstract (whatever that means). Interface
*values* are not abstract, though: they contain concrete values. The
words you quote are written from a Java mindset and I find them partly
helpful and partly misleading.


-rob
Reply all
Reply to author
Forward
0 new messages