具有处理程序功能时如何嵌入类型?

I'm working with a library that implements a type which accepts handlers and calls them for you when it should. I'd like to create a supertype that embeds the type and has properties beyond what the embedded type does. And I'd like to be able to use these properties in a handler.

Using my type as an argument fails the type checking, using the base type in handler decl works, but then I cant access the new fields. I am new to go, & would love to know how to do this, or what to suggest in changing the library to enable (Interfaces instead of the handler decl?)...

Contrived example:

    package main

    type Animal struct {
        Color   string
        feeders map[string]feeder
    }
    type feeder func(*Animal, string) string

    func (a *Animal) addFeeder(name string, fn feeder) {
        a.feeders[name] = fn
    }

    type mamal struct {
        Animal
        hair string
    }

    func feedHuman(m *mamal, food string) string {
        return "you got " + m.Color + " " + m.hair + " hair in your " + food
    }

    func main() {
        a := mamal{Animal{Color: "red"}, "bushy"}
        a.addFeeder("man", feedHuman)
        // fails to compile feedHuman needs to take *Animal but then cant access hair"
    }

You are right, you cannot do that because a mamal is not an Animal. There is no inheritance in go so this is not a solution. But you can achieve this behaviour with interfaces. By the way, your code does not work because you didn't initialize the feeders map, so you will get a problem after compilation.

Solution 1: Use type assertion

package main

import "fmt"

type Animal struct {
    Color   string
    feeders map[string]feeder
}
type feeder func(interface{}, string) string

func (a *Animal) addFeeder(name string, fn feeder) {
    a.feeders[name] = fn
}

type mamal struct {
    Animal
    hair string
}

func feedHuman(i interface{}, food string) string {
    m := i.(mamal)
    return "you got " + m.Color + " " + m.hair + " hair in your " + food
}

func main() {
    a := mamal{Animal{feeders: make(map[string]feeder), Color: "red"}, "bushy"}
    a.addFeeder("man", feedHuman)
    fmt.Println(a.feeders["man"](a, "pineapple"))
    // => you got red bushy hair in your pineapple
}

This is a bit dangerous because if the interface you pass is not a mamal, it will panic.

Second solution: Use a Feeder interface

package main

import "fmt"

type Feeder interface {
    Feed(string) string
}

type Animal struct {
    Color   string
    feeders map[string]Feeder
}

func (a *Animal) addFeeder(name string, feeder Feeder) {
    a.feeders[name] = feeder
}

type mamal struct {
    Animal
    hair string
}

func (m *mamal) Feed(food string) string {
    return "you got " + m.Color + " " + m.hair + " hair in your " + food
}

func main() {
    a := &mamal{Animal{Color: "red", feeders: make(map[string]Feeder)}, "bushy"}
    a.addFeeder("man", a)
    fmt.Println(a.feeders["man"].Feed("pineapple"))
    // you got red bushy hair in your pineapple
}

Though it works just as fine, it limits the number of handlers to one, so I do not think this is what you seek.