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
+
+
+
+
+
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())
+
+
+
+
+
+
+
+
+
+
+
typedescriberinterface{
+ 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.