From 35ad9cc35c4a9b4c89fd17ba61bdf67d7725e10c Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Mon, 22 Nov 2021 12:48:11 -0800 Subject: [PATCH] Add example of struct embedding in Go Also mention implementing interfaces with embedding Fixes #381 Fixes #398 --- examples.txt | 1 + examples/embedding/embedding.go | 59 +++++++ examples/embedding/embedding.hash | 2 + examples/embedding/embedding.sh | 5 + public/embedding | 248 ++++++++++++++++++++++++++++++ public/errors | 2 +- public/index.html | 2 + public/interfaces | 4 +- 8 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 examples/embedding/embedding.go create mode 100644 examples/embedding/embedding.hash create mode 100644 examples/embedding/embedding.sh create mode 100644 public/embedding diff --git a/examples.txt b/examples.txt index cadc52c..3f1d3e0 100644 --- a/examples.txt +++ b/examples.txt @@ -18,6 +18,7 @@ Pointers Structs Methods Interfaces +Embedding Errors Goroutines Channels diff --git a/examples/embedding/embedding.go b/examples/embedding/embedding.go new file mode 100644 index 0000000..f198daf --- /dev/null +++ b/examples/embedding/embedding.go @@ -0,0 +1,59 @@ +// Go support _embedding_ of structs and interfaces +// to express a more seamless _composition_ of types. + +package main + +import "fmt" + +type base struct { + num int +} + +func (b base) describe() string { + return fmt.Sprintf("base with num=%v", b.num) +} + +// A `container` _embeds_ a `base`. An embedding looks +// like a field without a name. +type container struct { + base + str string +} + +func main() { + + // When creating structs with literals, we have to + // initialize the embedding explicitly; here the + // embedded type serves as the field name. + co := container{ + base: base{ + num: 1, + }, + str: "some name", + } + + // We can access the base's fields directly on `co`, + // e.g. `co.num`. + fmt.Printf("co={num: %v, str: %v}\n", co.num, co.str) + + // Alternatively, we can spell out the full path using + // the embedded type name. + fmt.Println("also num:", co.base.num) + + // Since `container` embeds `base`, the methods of + // `base` also become methods of a `container`. Here + // we invoke a method that was embedded from `base` + // directly on `co`. + fmt.Println("describe:", co.describe()) + + type describer interface { + describe() string + } + + // Embedding structs with methods may be used to bestow + // interface implementations onto other structs. Here + // we see that a `container` now implements the + // `describer` interface because it embeds `base`. + var d describer = co + fmt.Println("describer:", d.describe()) +} diff --git a/examples/embedding/embedding.hash b/examples/embedding/embedding.hash new file mode 100644 index 0000000..fb9c195 --- /dev/null +++ b/examples/embedding/embedding.hash @@ -0,0 +1,2 @@ +8a15291c6e82b9c6873002e2aa5cef65907a3405 +Xtg07j06zBv diff --git a/examples/embedding/embedding.sh b/examples/embedding/embedding.sh new file mode 100644 index 0000000..316095e --- /dev/null +++ b/examples/embedding/embedding.sh @@ -0,0 +1,5 @@ +$ go run embedding.go +co={num: 1, str: some name} +also num: 1 +describe: base with num=1 +describer: base with num=1 diff --git a/public/embedding b/public/embedding new file mode 100644 index 0000000..7e089e1 --- /dev/null +++ b/public/embedding @@ -0,0 +1,248 @@ + + + + + Go by Example: Embedding + + + + +
+

Go by Example: Embedding

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Go support embedding of structs and interfaces +to express a more seamless composition of types.

+ +
+ + +
+ + + +
package main
+
+
+ + + +
import "fmt"
+
+
+ + + +
type base struct {
+    num int
+}
+
+
+ + + +
func (b base) describe() string {
+    return fmt.Sprintf("base with num=%v", b.num)
+}
+
+
+

A container embeds a base. An embedding looks +like a field without a name.

+ +
+ +
+type container struct {
+    base
+    str string
+}
+
+
+ + + +
func main() {
+
+
+

When creating structs with literals, we have to +initialize the embedding explicitly; here the +embedded type serves as the field name.

+ +
+ +
+    co := container{
+        base: base{
+            num: 1,
+        },
+        str: "some name",
+    }
+
+
+

We can access the base’s fields directly on co, +e.g. co.num.

+ +
+ +
+    fmt.Printf("co={num: %v, str: %v}\n", co.num, co.str)
+
+
+

Alternatively, we can spell out the full path using +the embedded type name.

+ +
+ +
+    fmt.Println("also num:", co.base.num)
+
+
+

Since container embeds base, the methods of +base also become methods of a container. Here +we invoke a method that was embedded from base +directly on co.

+ +
+ +
+    fmt.Println("describe:", co.describe())
+
+
+ + + +
    type describer interface {
+        describe() string
+    }
+
+
+

Embedding structs with methods may be used to bestow +interface implementations onto other structs. Here +we see that a container now implements the +describer interface because it embeds base.

+ +
+ +
+    var d describer = co
+    fmt.Println("describer:", d.describe())
+}
+
+
+ + + + + + + + +
+ + + +
$ go run embedding.go
+co={num: 1, str: some name}
+also num: 1
+describe: base with num=1
+describer: base with num=1
+
+ + +

+ Next example: Errors. +

+ + + + +
+ + + + diff --git a/public/errors b/public/errors index ba8282e..4ac669a 100644 --- a/public/errors +++ b/public/errors @@ -9,7 +9,7 @@ onkeydown = (e) => { if (e.key == "ArrowLeft") { - window.location.href = 'interfaces'; + window.location.href = 'embedding'; } diff --git a/public/index.html b/public/index.html index 3e5e0af..279ae86 100644 --- a/public/index.html +++ b/public/index.html @@ -67,6 +67,8 @@
  • Interfaces
  • +
  • Embedding
  • +
  • Errors
  • Goroutines
  • diff --git a/public/interfaces b/public/interfaces index e743386..578bfab 100644 --- a/public/interfaces +++ b/public/interfaces @@ -14,7 +14,7 @@ if (e.key == "ArrowRight") { - window.location.href = 'errors'; + window.location.href = 'embedding'; } } @@ -222,7 +222,7 @@ these structs as arguments to measure.

    - Next example: Errors. + Next example: Embedding.