Using interfaces to select converted struct

I’m new to Go and learning by translating a C++ program I have into Go.

The problem is that I have a graph with many types of nodes. In C++ this involves a base class and other classes built from that, along with coercing pointers to the base class into the correct node type.

My understanding is that I can do this in Go with interfaces and conversions. What I have so far (simplified) is

type Base struct{
  id int
  up int
  }

type Node struct{
  Base
  left,right,down int
  }

type Leaf struct{
  Base
  val string
  }

//and this is just a huge guess that doesn't work
type NodeIf interface{
   Node
   }

type LeafIf interface{
   Leaf
   }

func myfunc( vec []Base, a int){
   if n,ok := vec[a](NodeIf); ok{
      //do something with n as a Node
   }else{
      //gack! panic
     }
}

The question is, hopefully, how do I make an interface that says something is a struct of a certain type?

Thanks.

An interface in Go means “the type has methods specified in the interface”. I tried to recreate your example to show how this could be done. Since the structs don’t share any methods already, I defined an interface with a dummy one and implemented it for Base.

package main

import "fmt"

type Base struct {
	id int
	up int
}

// This will satisfy the `Based` interface defined below for all structs that embed Base.
func (b Base) Dummy() {}

type Node struct {
	Base
	left, right, down int
}

type Leaf struct {
	Base
	val string
}

type Based interface {
	Dummy()
}

func myfunc(vec []Based, a int) error {
	val := vec[a]
	switch val.(type) {
	case Node:
		fmt.Println("Doing something with Node")
	default:
		return fmt.Errorf("gack! unexpected type %T", val)
	}
	return nil
}

func main() {
	vec := []Based{
		Node{},
		Leaf{},
		Node{},
		Node{},
	}
	err := myfunc(vec, 3)
	fmt.Println("returned error:", err)
	err = myfunc(vec, 1)
	fmt.Println("returned error:", err)
}

Have fun.

1 Like

Thank you. Now I understand a lot more about interfaces. The bit of brilliance is that variables declared with a specific interface can then be used in the val.(type) or val.(some-type-that-meets-the-interface) constructs.