Variant Types in Go (Golang)

Here we Go again…

I had corresponded with some seasoned Go programmers about variant types some time ago. I was searching for a way to keep a slice of data where each element might be a different data-type. The approach I had been taking was in trying to define a data-structure that could act as a wrapper for some of the basic data types. I then learned through the wisdom of these developers that Go could already accommodate my needs in a much simpler fashion.

The interface is a facet of the Go programming language that allows one to define a set of behaviors (methods) that one may associate with any data-type. If one defines no behaviors/methods, the variable associated with the empty interface can assume any type.

Please consider the following program:

typetest1.go

// Copyright 2013 - by Jim Lawless
// License: MIT / X11
// See: http://www.mailsend-online.com/license2013.php
//
// Bear with me ... I'm a Go noob.
 
package main
 
import (
   "fmt"
)
 
var x interface{}
 
func main() {
   x=5
   i,ok := x.(int)
   if ok {
      fmt.Printf("x holds the integer value %d\n\n",i)
   }
 
   x="testo"
   var s=x.(string)
   fmt.Printf("The string value of x is now %s\n\n",s)
 
   x=5
   fmt.Printf("The runtime value of x is now %v\n\n",x)
}

The code initially defines a variable x as an implementer of an empty interface. The code then assigns the integer constant 5 to x.

The next portion of code tries to obtain an integer value from x into the integer variable i. The boolean variable ok will contain true if the conversion to integer was successful. The code will next test the conversion with the ok variable and can then print the integer if the conversion had been successful.

We see in the running output…

x holds the integer value 5

…indicating that the conversion has been a success.

In the next portion of code, a string constant is assigned to x. The code then attempts to print the contents as a string value. We see the output…

The string value of x is now testo

…indicating that the code was able to assign a string to a variable that had previously referred to an integer.

The final line of output in the code uses the %v formatting symbol to convert the variable to a displayable value regardless of the type. The code again assigns the integer value 5 to the variable x and calls fmt.Println(). The yielded output is:

The runtime value of x is now 5

My original need was to define a slice of variant data. Please consider this short program that keeps a string constant, an integer constant, and a boolean constant in a slice defined with empty interface characteristics:

typetest2.go

// Copyright 2013 - by Jim Lawless
// License: MIT / X11
// See: http://www.mailsend-online.com/license2013.php
//
// Bear with me ... I'm a Go noob.
 
package main
 
import  (
   "fmt"
)
 
var cells []interface{}=[]interface{}{ "x",124,true }
 
func main() {
   for i:=0; i<len(cells) ; i++ {
      fmt.Printf("Item %d ",i);
      switch( cells[i].(type) ) {
         case int:
            fmt.Printf("int :  %d\n",cells[i].(int))
            break;
         case string:
            fmt.Printf("string : %s\n",cells[i].(string))
            break;
         case bool:
            fmt.Printf("bool : %t\n",cells[i].(bool))
            break;
      }
   }
}

The code defines a variable named cells as a slice of items that implement the empty interface. Each element of the slice can then assume a different data-type.

The output yielded by the above code is:

Item 0 string : x
Item 1 int :  124
Item 2 bool : true

I hope to be able to use these concepts in newer programs, soon.

UPDATE 5 July, 2013: Please see Ralph Corderoy’s cleaner version here:

http://play.golang.org/p/1QhJ_M4ZOh