Go does not provide the typical, type-driven notion of subclassing,
    but it does have the ability to “borrow” pieces of an implementation by embedding types within a struct or interface

    interface embedding
    Embed two interfaces to form a new one. It is a union of the embedded interfaces.
    Only interfaces can be embedded within interfaces.

    1. // io package
    2. type Reader interface {
    3. Read(p []byte) (n int, err error)
    4. }
    5. type Writer interface {
    6. Write(p []byte) (n int, err error)
    7. }
    8. // ReadWriter is the interface that combines the Reader and Writer interfaces.
    9. type ReadWriter interface {
    10. Reader
    11. Writer
    12. }


    struct embedding**
    bufio package
    list the types within the struct but does not give them field names

    1. // ReadWriter stores pointers to a Reader and a Writer.
    2. // It implements io.ReadWriter.
    3. type ReadWriter struct {
    4. *Reader // *bufio.Reader
    5. *Writer // *bufio.Writer
    6. }

    bufio.ReadWriter not only has the methods of bufio.Reader and bufio.Writer, but also satisfies all three interfaces: io.Reader, io.Writer, and io.ReadWriter.

    an embedded field alongside a regular, name field

    1. type Job struct {
    2. Command string
    3. *log.Logger
    4. }
    5. // initializing
    6. func NewJob(command string, logger *log.Logger) *Job {
    7. return &Job{command, logger}
    8. }
    9. job := &Job{command, log.New(os.Stderr, "Job: ", log.Ldate)}
    10. // The Job type has the methods of *log.Logger
    11. job.Println("starting now...")
    12. //refer to an embedded field directly, using type name
    13. job.Logger.Println("refer directly")


    the rules to resolve name conflicts**

    1. A field or method X hides any other item X in a more deeply nested part of the type.
    2. If the same name appears at the same nesting level, it is usually an error;

    However, if the duplicate name is never mentioned outside the type definition, it is OK. (NOT in the same struct)

    it is OK, inner field is never mentioned outside the type definition

    1. type inner1 struct {
    2. field string
    3. }
    4. type inner2 struct {
    5. field string
    6. }
    7. type outer struct {
    8. inner1
    9. inner2
    10. }
    11. func main() {
    12. out := outer{
    13. inner1{"inner1"},
    14. inner2{"inner2"},
    15. }
    16. fmt.Println(out)
    17. }

    Ambiguous reference
    image.png
    Duplicate field
    image.png