DEV Community

林子篆
林子篆

Posted on • Originally published at dannypsnl.github.io on

A simple way to ensure interface won’t be implemented accidently

#go

Sample code is quite easy:

type Car interface {
    impl() Car
    Move()
}

type Animal interface {
    impl() Animal
    Walk()
}
Enter fullscreen mode Exit fullscreen mode

Now, let’s create a structure type:

type Duck struct {
    Animal
}
Enter fullscreen mode Exit fullscreen mode

Now, if you add func (d *Duck) Move(), you won’t be a car accident! What if you want to embed two interfaces?

type Duck struct {
    Car
    Animal
}
Enter fullscreen mode Exit fullscreen mode

The compiler would refuse the code since: Duck.impl is ambiguous, you can’t have two methods with the same name in Go definition. So we can use this to create something just like impl Trait for Type in Rust, although this is a workaround,but anyway I work with Go so I have to find out how to ensure this when we need it.

If you want to know what if we want something just take type has Move() method? Then just define:

type Movable interface {
    Move()
}
Enter fullscreen mode Exit fullscreen mode

The point is correctly reduce the concept in interface, and do not create interface has general name, unless you know what are you doing,but if you need a workaround, this is.

Since Go can’t write: func foo(bar A + B + C), A, B, C are interface, so I suggest write:

func foo(bar interface{
    A
    B
    C
})
Enter fullscreen mode Exit fullscreen mode

NOTE: newline is required, because Go compiler is stupid. You might want define a private interface for this function only.

Sad thing is we can’t use A | B | C, have to do runtime assertion for this.

One more bad thing is because you embedded the interface, Go won’t check you provide the implementation of methods or not, you have to do this manually.

Top comments (4)

Collapse
 
maxatome profile image
Maxime Soulé

Note you can do:

func foo(bar interface{ A; B; C; })

Even if it is not the gofmt style...

Collapse
 
dannypsnl profile image
林子篆

Few reasons why I don't show that:

  • as you say, gofmt would reformat it, in the most environment, gofmt is trigger by default
  • Go using newline to separate things in interface, at least, from user view it's, so semicolon would confuse others. Which means you just expose the details, I would that's a parser bug, since it should not allow the thing it does not courage you do.
Collapse
 
maxatome profile image
Maxime Soulé

It is not a parser bug, it is the go grammar. Perhaps do you think the grammar should be augmented? If yes, you can submit a proposal.
Just as a note one can read the go specification and more specifically the semicolons point.

Thread Thread
 
dannypsnl profile image
林子篆

Do you read the whole sentence? I say it's a bug since... I explain why I don't prefer that code, not try to get a specification reference, I read that a lot ok.
And then change the syntax almost impossible, it might break some code so Go won't accept it.
I have to point out: Go is ok, but of course not prefer, like any other thing.
If you can't accept anyone says it's a problem, fine, just end the conversation.