package main import ( "bufio" "errors" "fmt" "os" "strings" ) type Animal interface { Eat() Move() Speak() } type Cow struct { name string food string `default:"grass"` locomotion string `default:"walk"` sound string `default:"moo"` } func (a Cow) Eat() { fmt.Println(a.food) } func (a Cow) Move() { fmt.Println(a.locomotion) } func (a Cow) Speak() { fmt.Println(a.sound) } type Bird struct { Name string Food string `default:"worms"` Locomotion string `default:"fly"` Sound string `default:"peep"` } func (a Bird) Eat() { fmt.Println(a.Food) } func (a Bird) Move() { fmt.Println(a.Locomotion) } func (a Bird) Speak() { fmt.Println(a.Sound) } type Snake struct { Name string Food string `default:"mice"` Locomotion string `default:"slither"` Sound string `default:"hsss"` } func (a Snake) Eat() { fmt.Println(a.Food) } func (a Snake) Move() { fmt.Println(a.Locomotion) } func (a Snake) Speak() { fmt.Println(a.Sound) } func NewAnimal(name string, animalType string) (Animal, error) { switch animalType { case "cow": return Cow{name, "grass", "walk", "moo"}, nil case "bird": return Bird{name, "worms", "fly", "peep"}, nil case "snake": return Snake{name, "mice", "slither", "hiss"}, nil default: return Cow{}, errors.New(fmt.Sprintf("Error! Failed to create animal of type: %s. Options {cow, bird, snake}.", animalType)) } } func queryAnimal(animal Animal, query string) { switch query { case "eat": animal.Eat() case "move": animal.Move() case "speak": animal.Speak() default: fmt.Printf("Error! Query parameter: %s invalid. Options: {eat, move, speak}\n", query) } } // Use the empty interface to map string to Any type // var animalMap map[string]interface{} var animalMap map[string]Animal func main() { animalMap = make(map[string]Animal) scanner := bufio.NewScanner(os.Stdin) fmt.Println("\n\nWelcome to your personal animal database. Two commands are available {newanimal, query}\n") fmt.Println("The \"newanimal\" command takes two parameters (name, animalType) seperated by white space.") fmt.Println("\"newanimal\" animal types are restricted to {cow, bird, snake}") fmt.Println("Example: \"newanimal bob cow\"\n") fmt.Println("The \"query\" command takes two parameters (name, action) seperated by white space.") fmt.Println("\"query\" actions are restricted to {eat, move, speak}") fmt.Println("Example: \"query bob eat\"\n") for { fmt.Print(">") scanner.Scan() input := scanner.Text() input = strings.TrimSpace(input) splitInput := strings.Fields(input) // Ensure user command is proper size if len(splitInput) != 3 { fmt.Println("Error! Invalid input parameters. Please try again.") continue } command := splitInput[0] animalName := splitInput[1] arg := splitInput[2] switch command { case "newanimal": userAnimal, err := NewAnimal(animalName, arg) if err != nil { fmt.Println(err) continue } animalMap[animalName] = userAnimal case "query": // check animal is in datastore val, present := animalMap[animalName] if present { queryAnimal(val, arg) } else { fmt.Printf("Error! Failed to find animal %s in database\n", animalName) } default: fmt.Println("Error! Unrecognized user command. Options {newanimal, query}") } } }