// There is a problem that comes up in C++ a lot (in my experience) which has no // good C++ answer, but which Go has a great answer for (OMG, Tim said something // nice about Go!). The problem is: wrappers. // // I often find myself wanting to implement a particular interface (abstract base // class in C++) by delegating all method calls to another implementation of that // interface, but intercepting just one or two of them. I can't use inheritance // because I don't know the concrete type of the wrappee. So I implement my own // wrapper type, and I implement every one of the interface's methods as simple // calls to the wrappee. This works, but it can be INCREDIBLY tedious to do, // especially if the interface has a lot of methods. It works right up until // someone adds a new method to the base interface -- then my build breaks and I // have to implement it too. // // Go's answer is very elegant - embed the interface type to "inherit" methods, // "override" mthods you care about, and init from an instance of that interface. // // thockin@google.com package main import "fmt" import "math/rand" // Base interface I want to wrap. type Frobber interface { FrobGently() FrobAggressively() FrobWithPrejudice() } // One implementation. type wetFrobber struct{} func (wet wetFrobber) FrobGently() { fmt.Println("wet.FrobGently()") } func (wet wetFrobber) FrobAggressively() { fmt.Println("wet.FrobAggressively()") } func (wet wetFrobber) FrobWithPrejudice() { fmt.Println("wet.FrobWithPrejudice()") } // Another implementation. type dryFrobber struct{} func (dry dryFrobber) FrobGently() { fmt.Println("dry.FrobGently()") } func (dry dryFrobber) FrobAggressively() { fmt.Println("dry.FrobAggressively()") } func (dry dryFrobber) FrobWithPrejudice() { fmt.Println("dry.FrobWithPrejudice()") } // Choose a random implementation. func newFrobber() Frobber { // Yes, I know playground is not actually random. if rand.Intn(2) == 0 { return dryFrobber{} } return wetFrobber{} } // My wrapper. type FrobWrapper struct { Frobber } // Override just one method. func (wrap FrobWrapper) FrobWithPrejudice() { fmt.Printf("OMG: ") wrap.Frobber.FrobWithPrejudice() } func main() { var f Frobber = FrobWrapper{newFrobber()} f.FrobGently() f.FrobAggressively() f.FrobWithPrejudice() }

About the Playground

The Go Playground is a web service that runs on golang.org's servers. The service receives a Go program, vets, compiles, links, and runs the program inside a sandbox, then returns the output.

If the program contains tests or examples and no main function, the service runs the tests. Benchmarks will likely not be supported since the program runs in a sandboxed environment with limited resources.

There are limitations to the programs that can be run in the playground:

The playground can use most of the standard library, with some exceptions. The only communication a playground program has to the outside world is by writing to standard output and standard error.

In the playground the time begins at 2009-11-10 23:00:00 UTC (determining the significance of this date is an exercise for the reader). This makes it easier to cache programs by giving them deterministic output.

There are also limits on execution time and on CPU and memory usage.

The article "Inside the Go Playground" describes how the playground is implemented. The source code is available at https://go.googlesource.com/playground.

The playground uses the latest stable release of Go.

The current version is go1.14.8.

The playground service is used by more than just the official Go project (Go by Example is one other instance) and we are happy for you to use it on your own site. All we ask is that you contact us first (note this is a public mailing list), use a unique user agent in your requests (so we can identify you), and that your service is of benefit to the Go community.

Any requests for content removal should be directed to security@golang.org. Please include the URL and the reason for the request.