I would like to propose allowing annotations (tags) on Interface types. 
Only a subset of an Interfaces methods could be tagged. This subset is 
defined as methods that have a single return type and take no parameters 
(as a best practice, these methods should not change any state and be 
thread safe...). 

So let's use the 'Go by example Interface', found here:
https://gobyexample.com/interfaces
and
https://play.golang.org/p/313UebA3rD

I have an altered version of this, where I have capitalized the methods of 
interest and added tags: https://play.golang.org/p/50oEQHeWVZ

// _Interfaces_ are named collections of method
// signatures.

package main

import "fmt"
import "math"

// Here's a basic interface for geometric shapes.
type geometry interface {
    Area() float64 `json:"area"`
    Perim() float64 `json:"perimeter"`
}

// For our example we'll implement this interface on
// `rect` and `circle` types.
type rect struct {
    width, height float64
}
type circle struct {
    radius float64
}

// To implement an interface in Go, we just need to
// implement all the methods in the interface. Here we
// implement `geometry` on `rect`s.
func (r rect) Area() float64 {
    return r.width * r.height
}
func (r rect) Perim() float64 {
    return 2*r.width + 2*r.height
}

// The implementation for `circle`s.
func (c circle) Area() float64 {
    return math.Pi * c.radius * c.radius
}
func (c circle) Perim() float64 {
    return 2 * math.Pi * c.radius
}

// If a variable has an interface type, then we can call
// methods that are in the named interface. Here's a
// generic `measure` function taking advantage of this
// to work on any `geometry`.
func measure(g geometry) {
    fmt.Println(g)
    fmt.Println(g.Area())
    fmt.Println(g.Perim())
}

func main() {
    r := rect{width: 3, height: 4}
    c := circle{radius: 5}

    // The `circle` and `rect` struct types both
    // implement the `geometry` interface so we can use
    // instances of
    // these structs as arguments to `measure`.
    measure(r)
    measure(c)
}

What happens? When a tag processor is engaged on an interface containing 
tags, instead of using value of the fields of a struct that are tagged, it 
takes the value returned by the invocation of the methods that are tagged 
(it invokes the method and uses the (single) value returned). 

So what does this give us? It means I can have a list of type geometry 
(interface) that contains both circle and square structs under the hood, 
and I can walk through the list and (for example) serialize them, using the 
serialization defined in the interface

It gives a bit of generic feel to things, at least from a tags perspective. 
[Sorry, I said the 'G' word]

I guess reflect.Method <https://golang.org/pkg/reflect/#Method> would need 
a Tag StructTag <https://golang.org/pkg/reflect/#StructTag> like that in 
reflect.StructField. <https://golang.org/pkg/reflect/#StructField>

I think this would be backward compatible, and just a handful of things 
would need to be updated in reflect (from my limited knowledge) as well as 
some minor changes to the compiler (??) and likely other things I don't 
know about, like various tool chain stuff, etc, ??.

Thanks,
Glen

-- 
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.

Reply via email to