I want to make a linked list which can hold the values of any type but the linked list must hold values of any one type only.
In general when I am using interfaces for achieving this - any type which implements the interface for the node can be added to the linked list.
I have written an implementation for this where whenever a new key is added to the linked list, the type of the key is checked against the type of the key at the head. I want to understand if this is the correct way of implementing it or is there a better way of doing it.
package main
import (
"errors"
"fmt"
"reflect"
"strings"
)
type MyNode struct {
value int
}
func (node *MyNode) PrintValue() {
fmt.Printf(" %d ", node.value)
}
type llNode struct {
key llNodeInterface
next *llNode
llNodeType reflect.Type
}
type llNodeInterface interface {
PrintValue()
}
type ComplexNode struct {
realValue int
imageValue int
}
func (node *ComplexNode) PrintValue() {
fmt.Printf(" %d + i%d", node.realValue, node.imageValue)
}
// Student type.
type Student struct {
name string
age int
}
// Student implements the PrintValue function - thus llNodeInterface is implemented.
func (node *Student) PrintValue() {
fmt.Printf("Name: %s | Age : %d ", node.name, node.age)
}
// Function which will check the of the new node before adding to the linked
// list. It checks the type of the new key against the type of the key in the
// head. If both are equal then it proceed else return error.
func (head *llNode) AddBeforeHeadTypeCheck(passedKey llNodeInterface) error {
if head.key == nil {
head.key = passedKey
head.llNodeType = reflect.TypeOf(head.key)
} else {
typeOfPassedKey := reflect.TypeOf(passedKey)
if typeOfPassedKey != head.llNodeType {
fmt.Printf("
Unsupported type for the type %T", passedKey)
return errors.New("Type mistmatch")
}
temp := llNode{key: head.key, next: head.next}
head.key = passedKey
head.next = &temp
}
return nil
}
// Function which will not check the types and will simply add the new node to
// the linked list. Thus linked list will be able to have nodes of multiple
// types.
func (head *llNode) AddBeforeHead(passedKey llNodeInterface) {
if head.key == nil {
head.key = passedKey
head.llNodeType = reflect.TypeOf(head.key)
} else {
temp := llNode{key: head.key, next: head.next}
head.key = passedKey
head.next = &temp
}
}
func (head *llNode) Init() {
head.key = nil
head.next = nil
head.llNodeType = nil
}
// Print the linked list.
func (head *llNode) DisplayLL() {
temp := head
fmt.Printf("
%s", strings.Repeat("#", 80))
fmt.Printf("
Printing the linked list
")
for {
if temp.key == nil {
fmt.Println("Linked list is empty")
break
} else {
fmt.Printf("
%T %v ", temp.key, temp.key)
key := temp.key
key.PrintValue()
if temp.next == nil {
break
} else {
temp = temp.next
}
}
}
fmt.Printf("
%s", strings.Repeat("#", 80))
fmt.Printf("
")
}
func testWithMixedType() {
head := llNode{}
head.Init()
for i := 1; i < 10; i++ {
temp := &ComplexNode{i, i * 10}
head.AddBeforeHeadTypeCheck(temp)
}
temps := &Student{"rishi", 20}
head.AddBeforeHeadTypeCheck(temps) // Will give error.
head.DisplayLL()
}
func testWithComplexNumber() {
head := llNode{}
head.Init()
for i := 1; i < 10; i++ {
temp := &ComplexNode{i, i * 10}
head.AddBeforeHeadTypeCheck(temp)
}
}
func main() {
testWithComplexNumber()
testWithMixedType()
}
The code is working fine - but I want to understand if there is a better or different way of doing this.
Also - what is the performance impact of the current checking of types using the reflect package. Is there a different way of achieving the same thing.
Unsupported type for the type *main.Student
Unsupported type for the type *main.Student
################################################################################
Printing the linked list
*main.ComplexNode &{9 90} 9 + i90
*main.ComplexNode &{8 80} 8 + i80
*main.ComplexNode &{7 70} 7 + i70
*main.ComplexNode &{6 60} 6 + i60
*main.ComplexNode &{5 50} 5 + i50
*main.ComplexNode &{4 40} 4 + i40
*main.ComplexNode &{3 30} 3 + i30
*main.ComplexNode &{2 20} 2 + i20
*main.ComplexNode &{1 10} 1 + i10
################################################################################