You can easily and cleanly work around this by exposing getter and setter method in your interface.
You can easily and cleanly work around this by exposing getter and setter method in your interface.
Rust is the same I think, where you'd need to have methods that explicitly implement the trait (interface in Go). However, Rust has a built-in code generation tool (macros), and you can decorate your structs to have it automatically implement some traits for you. That's the equivalent of adding one more entry to your Go generated code loop, except that it's right next to the struct.
If Go did support field methods (which it looks like they may one day), that might be the tipping point for me for disabling a bunch of generated code. Not sure if there's other things getting in my way, because I gave up once I noticed I couldn't do that.
BTW, accessing common fields is temporarily disabled before releasing Go 1.18, because there is another fundamental problem which needs to be resolved firstly.
Concepts?
So, how do I specify, using concepts, that my template expects a type which has a field “.foo” of type int?
template<typename T>
concept has_foo = requires(T x){
{ x.foo } -> std::same_as<int>;
};
template<has_foo T>
int get_foo(T x){...}
// or
template<typename T>
requires has_foo<T>
void f(T x){...}
// or even
void f(has_foo auto x) {...}type hasFoo interface {
getfoo() int
setfoo(int)
}func f(hasFoo) {}
?
func f[T interface{.Foo}](T) {}
Of course, this doesn't exist in Go, so we must do: func f[T interface{GetFoo(); SetFoo()}](T) {}
And then define setters and getters on every type we want to use, including defining new types (with the commensurate setters/getters) for types that we don't own (i.e., if you import a struct from another package and it doesn't have setters and getters defined, you have to create a new type that implements those setters/getters). foo.baz = 1; // baz could be a int or could be a setter.
int baz = foo.baz; // same