diff --git a/clients/go/Readme.md b/clients/go/Readme.md
new file mode 100644
index 00000000..77950c23
--- /dev/null
+++ b/clients/go/Readme.md
@@ -0,0 +1,40 @@
+Set directory path that contains superposition object files in SUPERPOSITION_LIB_PATH env variable;
+
+Set directory path that contains C header file SUPERPOSITION_INCLUDE_PATH env variable;
+
+ export CGO_CFLAGS="-I${SUPERPOSITION_INCLUDE_PATH}" (Set this flag in order to know go where to pick C header file from).
+
+## [ CAC Client ](./cacclient/main.go)
+
+* #### export CGO_LDFLAGS="-L${SUPERPOSITION_LIB_PATH} -lcac_client" (Set this flag in order to know go where to pick superposition object files from).
+1. This exports a class that exposes functions that internally call rust functions.
+2. For Different platform it read different superposition object files.
+ * For Mac -> libcac_client.dylib
+ * For Windows -> libcac_client.so
+ * For Linux -> libcac_client.dll
+3. This run CAC CLient in two thread one is main thread another is worker thread.
+4. Polling updates for config are done on different thread. ([ref](./cacclient/main.go#50)).
+
+
+## [ Experimentation Client ](./expclient/main.go)
+
+* #### export CGO_LDFLAGS="-L${SUPERPOSITION_LIB_PATH} -lexperimentation_client" (Set this flag in order to know go where to pick superposition object files from).
+1. This exports a class that exposes functions that internally call rust functions.
+2. For Different platform it read different superposition object files.
+ * For Mac -> libexperimentation_client.dylib
+ * For Windows -> libexperimentation_client.so
+ * For Linux -> libexperimentation_client.dll
+3. This run Experimentation CLient in two thread one is main thread another is worker thread.
+4. Polling updates for experiments are done on different thread. ([ref](./expclient/main.go#55)).
+
+
+## [ Test ](./main.go)
+
+* #### export CGO_LDFLAGS="-L${SUPERPOSITION_LIB_PATH} -lcac_client -lexperimentation_client" (Set this to run sample project)
+1. To test this sample project follow below steps.
+ * Run superposition client.
+ * Run **go run main.go** .
+2. By Default this sample code uses [dev](./main.go#L11) tenant.
+3. By Default this sample code assumes superposition is running on [8080](./main.go#L13) port.
+3. By Default this sample code polls superposition every [1 second](./main.go#L12) port.
+4. This sample code creates both [CAC CLient](./main.go#15) and [Experimentation Client](./main.go#20) with above default values.
\ No newline at end of file
diff --git a/clients/go/cacclient/main.go b/clients/go/cacclient/main.go
new file mode 100644
index 00000000..c793f8a1
--- /dev/null
+++ b/clients/go/cacclient/main.go
@@ -0,0 +1,158 @@
+package cacclient
+
+/*
+#include "libcac_client.h"
+*/
+import "C"
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+ "unsafe"
+)
+
+// CacClient struct
+type CacClient struct {
+ tenant string
+ pollingFrequency int
+ cacHostName string
+ delimiter string
+}
+
+// NewCacClient creates a new CacClient
+func NewCacClient(tenantName string, pollingFrequency int, cacHostName string) *CacClient {
+ return &CacClient{tenant: tenantName, pollingFrequency: pollingFrequency, cacHostName: cacHostName, delimiter: ","}
+}
+
+// GetCacLastErrorMessage gets the last error message from the C library
+func (c *CacClient) GetCacLastErrorMessage() string {
+ return C.GoString(C.cac_last_error_message())
+}
+
+// GetCacLastErrorLength gets the length of the last error message
+func (c *CacClient) GetCacLastErrorLength() int {
+ return int(C.cac_last_error_length())
+}
+
+// GetCacClient gets the client pointer from the C library
+func (c *CacClient) GetCacClient() *C.Arc_Client {
+ return C.cac_get_client(C.CString(c.tenant))
+}
+
+// CreateNewCacClient creates a new client in the C library
+func (c *CacClient) CreateNewCacClient() int {
+ resp := C.cac_new_client(C.CString(c.tenant), C.ulong(c.pollingFrequency), C.CString(c.cacHostName))
+ if resp == 1 {
+ errorMessage := c.GetCacLastErrorMessage()
+ fmt.Printf("Some Error Occur while creating new client: %s\n", errorMessage)
+ }
+ return int(resp)
+}
+
+// StartCacPollingUpdate starts polling updates in a separate goroutine
+func (c *CacClient) StartCacPollingUpdate() {
+ tenant := C.CString(c.tenant)
+ go C.cac_start_polling_update(tenant)
+}
+
+// GetCacConfig gets the configuration from the C library
+func (c *CacClient) GetCacConfig(filterQuery *map[string]string, filterPrefix *[]string) string {
+ var strFilterPrefix, strFilterQuery *string
+
+ if filterPrefix != nil {
+ val := strings.Join(*filterPrefix, c.delimiter)
+ strFilterPrefix = &val
+ }
+
+ if filterQuery != nil {
+ byteVal, err := json.Marshal(filterQuery)
+ if err != nil {
+ fmt.Println("Failed to covert json to string")
+ return ""
+ }
+ strVal := string(byteVal)
+ strFilterQuery = &strVal
+ }
+ clientPtr := c.GetCacClient()
+ var fp, fq *C.char
+
+ if strFilterPrefix != nil {
+ fp = C.CString(*strFilterPrefix)
+ } else {
+ fp = nil
+ }
+
+ if strFilterQuery != nil {
+ fq = C.CString(*strFilterQuery)
+ } else {
+ fq = nil
+ }
+ return C.GoString(C.cac_get_config(clientPtr, fq, fp))
+}
+
+// FreeCacClient frees the client in the C library
+func (c *CacClient) FreeCacClient(clientPtr string) {
+ ptr := c.GetCacClient()
+ C.cac_free_client(ptr)
+}
+
+// FreeCacString frees a string in the C library
+func (c *CacClient) FreeCacString(s string) {
+ cs := C.CString(s)
+ defer C.free(unsafe.Pointer(cs))
+ C.cac_free_string(cs)
+}
+
+// GetLastModified gets the last modified timestamp from the C library
+func (c *CacClient) GetLastModified() string {
+ clientPtr := c.GetCacClient()
+ return C.GoString(C.cac_get_last_modified(clientPtr))
+}
+
+// GetResolvedConfig gets the resolved configuration from the C library
+func (c *CacClient) GetResolvedConfig(query map[string]string, filterKeys *[]string, mergeStrategy string) string {
+
+ var strfilterKeys *string
+
+ if filterKeys != nil {
+ val := strings.Join(*filterKeys, c.delimiter)
+ strfilterKeys = &val
+ }
+
+ var fk *C.char
+ if strfilterKeys != nil {
+ fk = C.CString(*strfilterKeys)
+ } else {
+ fk = nil
+ }
+ clientPtr := c.GetCacClient()
+ strQuery, err := json.Marshal(query)
+ if err != nil {
+ fmt.Println("Failed to covert json to string")
+ return ""
+ }
+ q := C.CString(string(strQuery))
+ ms := C.CString(mergeStrategy)
+
+ return C.GoString(C.cac_get_resolved_config(clientPtr, q, fk, ms))
+}
+
+// GetDefaultConfig gets the default configuration from the C library
+func (c *CacClient) GetDefaultConfig(filterKeys *[]string) string {
+ clientPtr := c.GetCacClient()
+ var strfilterKeys *string
+
+ if filterKeys != nil {
+ val := strings.Join(*filterKeys, c.delimiter)
+ strfilterKeys = &val
+ }
+
+ var fk *C.char
+ if strfilterKeys != nil {
+ fk = C.CString(*strfilterKeys)
+ } else {
+ fk = nil
+ }
+
+ return C.GoString(C.cac_get_default_config(clientPtr, fk))
+}
diff --git a/clients/go/expclient/main.go b/clients/go/expclient/main.go
new file mode 100644
index 00000000..5db2a001
--- /dev/null
+++ b/clients/go/expclient/main.go
@@ -0,0 +1,124 @@
+package expclient
+
+/*
+#include "libexperimentation_client.h"
+*/
+import "C"
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+// Define ExperimentationClient structure
+type ExperimentationClient struct {
+ tenant string
+ pollingFrequency int
+ cacHostName string
+ delimiter string
+}
+
+// Constructor
+func NewExperimentationClient(tenant string, pollingFrequency int, hostName string) *ExperimentationClient {
+ return &ExperimentationClient{
+ tenant: tenant,
+ pollingFrequency: pollingFrequency,
+ cacHostName: hostName,
+ delimiter: ",",
+ }
+}
+
+// Methods
+func (ec *ExperimentationClient) CreateNewExperimentationClient() int {
+ respCode := C.expt_new_client(C.CString(ec.tenant), C.ulong(ec.pollingFrequency), C.CString(ec.cacHostName))
+ if respCode == 1 {
+ errorMessage := C.GoString(C.expt_last_error_message())
+ fmt.Printf("Error occurred while creating new experimentation client: %s\n", errorMessage)
+ return int(respCode)
+ }
+ return int(respCode)
+}
+
+func (ec *ExperimentationClient) GetExperimentationClient() *C.Arc_Client {
+ return C.expt_get_client(C.CString(ec.tenant))
+}
+
+func (ec *ExperimentationClient) GetRunningExperiments() string {
+ clientPtr := ec.GetExperimentationClient()
+ return C.GoString(C.expt_get_running_experiments(clientPtr))
+}
+
+func (ec *ExperimentationClient) FreeString(str string) {
+ C.expt_free_string(C.CString(str))
+}
+
+func (ec *ExperimentationClient) StartExperimentationPollingUpdate() {
+ go C.expt_start_polling_update(C.CString(ec.tenant))
+}
+
+func (ec *ExperimentationClient) GetExperimentationLastErrorLength() int {
+ return int(C.expt_last_error_length())
+}
+
+func (ec *ExperimentationClient) FreeExperimentationClient() {
+ clientPtr := ec.GetExperimentationClient()
+ C.expt_free_client(clientPtr)
+}
+
+func (ec *ExperimentationClient) GetFilteredSatisfiedExperiments(context map[string]string, filterPrefix *[]string) string {
+ clientPtr := ec.GetExperimentationClient()
+ strContext, err := json.Marshal(context)
+ if err != nil {
+ fmt.Println("Failed to covert json to string")
+ return ""
+ }
+ var strFilterPrefix *string
+
+ if filterPrefix != nil {
+ val := strings.Join(*filterPrefix, ec.delimiter)
+ strFilterPrefix = &val
+ }
+
+ var fk *C.char
+ if strFilterPrefix != nil {
+ fk = C.CString(*strFilterPrefix)
+ } else {
+ fk = nil
+ }
+
+ return C.GoString(C.expt_get_filtered_satisfied_experiments(clientPtr, C.CString(string(strContext)), fk))
+}
+
+func (ec *ExperimentationClient) GetApplicableVariant(context map[string]string, toss int) string {
+ clientPtr := ec.GetExperimentationClient()
+ strContext, err := json.Marshal(context)
+ if err != nil {
+ fmt.Println("Failed to covert json to string")
+ return ""
+ }
+ return C.GoString(C.expt_get_applicable_variant(clientPtr, C.CString(string(strContext)), C.short(toss)))
+}
+
+func (ec *ExperimentationClient) GetSatisfiedExperiments(context map[string]string, filterPrefix *[]string) string {
+ clientPtr := ec.GetExperimentationClient()
+ strContext, err := json.Marshal(context)
+ var strFilterPrefix *string
+
+ if filterPrefix != nil {
+ val := strings.Join(*filterPrefix, ec.delimiter)
+ strFilterPrefix = &val
+ }
+
+ var fk *C.char
+ if strFilterPrefix != nil {
+ fk = C.CString(*strFilterPrefix)
+ } else {
+ fk = nil
+ }
+
+ if err != nil {
+ fmt.Println("Failed to covert json to string")
+ return ""
+ }
+ return C.GoString(C.expt_get_satisfied_experiments(clientPtr, C.CString(string(strContext)), fk))
+}
diff --git a/clients/go/go.mod b/clients/go/go.mod
new file mode 100644
index 00000000..552e14e4
--- /dev/null
+++ b/clients/go/go.mod
@@ -0,0 +1,3 @@
+module goclients
+
+go 1.22.5
diff --git a/clients/go/main.go b/clients/go/main.go
new file mode 100644
index 00000000..057fd7de
--- /dev/null
+++ b/clients/go/main.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "fmt"
+ "goclients/cacclient"
+ "goclients/expclient"
+)
+
+func main() {
+ // Example usage
+ tenant := "dev"
+ pollingFrequency := 1
+ cachostName := "http://localhost:8080"
+
+ client := cacclient.NewCacClient(tenant, pollingFrequency, cachostName)
+ client.CreateNewCacClient()
+ fmt.Println("Default Configs", client.GetCacConfig(nil, nil))
+
+ expClient := expclient.NewExperimentationClient(tenant, pollingFrequency, cachostName)
+ expClient.CreateNewExperimentationClient()
+ fmt.Println("Running experiments:", expClient.GetRunningExperiments())
+}