Design Pattern: Proxy Pattern in Go

Proxy pattern represents remote objects locally, this way the local object is used as a proxy of the remote object. The local one can be used in all cases where the remote object is required.

The local object can also add some additional functionality/checking while referring to the remote object.

This article demonstrates Proxy pattern implementations in Golang. Check the implementation details below.

Implementation

Here are the steps to implement Proxy pattern in Go-

  • Declare an interface, which can be used by both the remote and local structs.
  • Define the remote struct as per requirement. The method implementations for the struct contains the actual functionality.
  • Define the proxy struct.
  • Declare a field in the proxy to store the reference to the actual struct.
  • In the method implementation of proxy check if a reference to the proxy is already initiated. If not then initiate the proxy.
  • Then in the proxy method call the method(s) from the actual struct. Add any checking or access control or enhancements in the method if required.

Examples

Here are a few examples of the Proxy pattern implementation in Go-

Example #1: Simple Proxy

Here is the simplest proxy example.

Proxy Interface

  • Create file “proxy_interface.go”.
  • Define interface “ProxyI”.
  • Declare methods as per requirement. There is no specific rule for this.
  • Use/implement the interface for the actual and proxy struct.
// proxy_interface.go

package main

type ProxyI interface {
	Operation1()
	Operation2()
}

Item Class

  • Create file “actual.go”.
  • Define struct “Actual”.
  • Define method “NewActual” which will create a new “Actual” struct and return that.
  • Implement interface “ProxyI” for the “Actual” struct. Write the method implementation as per requirement, for the interface implementation.
// actual.go

package main

import "fmt"

type Actual struct {}

func NewActual() (actual *Actual) {
	actual = &Actual{}
	return
}
func (actual *Actual) Operation1() {
	fmt.Println("Performing operation 1 in the Actual Object")
}

func (actual *Actual) Operation2() {
	fmt.Println("Performing operation 2 in the Actual Object")
}

Proxy Class

  • Create file “proxy.go”.
  • Define struct “Proxy”.
  • Declare a field “actual” of the type “Actual” struct. This will be used to store a reference to an “Actual” struct.
  • Define the method “NewProxy”. This method creates a initiate “Proxy” struct and returns that.
  • Implement interface “ProxyI” for the “Proxy” struct. Define methods (Operation1 and Operation2) as part of the proxy interface implementation.
  • In the method implementation check if the “actual” is nil or already initiated, if not initiated then initiate that using the “NewActual” method.
  • In the method implementation call methods from the “actual”. 
  • Add any checking or additional functionality if required.
// proxy.go

package main

type Proxy struct {
	actual ProxyI
}

func NewProxy() (proxy *Proxy) {
	proxy = &Proxy{}
	return
}

func (proxy *Proxy) Operation1() {
	if proxy.actual == nil {
		proxy.actual = NewActual()
	}
	proxy.actual.Operation1()
}

func (proxy *Proxy) Operation2() {
	if proxy.actual == nil {
		proxy.actual = NewActual()
	}
	proxy.actual.Operation2()
}

Demo

Using the proxy implementation is simple, just initiate the the “Proxy” struct and use that.

// main.go

package main

func main() {
	proxy := NewProxy()
	proxy.Operation1()
	proxy.Operation2()
}

Output

Output of the demo code will be as below.

Performing operation 1 in the Actual Object
Performing operation 2 in the Actual Object

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Proxy pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.