-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
135 lines (106 loc) · 2.88 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"fmt"
"sort"
)
type englishBot struct{}
type spanishBot struct{}
type bot interface {
getGreeting() string
}
func (englishBot) getGreeting() string {
return "Hello"
}
func (spanishBot) getGreeting() string {
return "Hola"
}
func printGreeting(b bot) {
fmt.Println(b.getGreeting())
}
// a. Introduction and declaration
// We've already declared the 'bot' interface above
// b. Implementing an interface
// i. Implicit Interface (already demonstrated with englishBot and spanishBot)
// ii. Polymorphism: Interface as a contract
type germanBot struct{}
func (germanBot) getGreeting() string {
return "Hallo"
}
// c. Empty interface. Same as any which is alias for interface{}
func printAnything(a interface{}) {
fmt.Printf("Value: %v, Type: %T\n", a, a)
}
// d. Method set
type reader interface {
read() string
}
type writer interface {
write(string)
}
type readWriter interface {
reader
writer
}
// e. Frequently used built-in/stdlib interfaces
// i. Stringer interface
type person struct {
name string
age int
}
func (p person) String() string {
return fmt.Sprintf("%s (%d years)", p.name, p.age)
}
// ii. Interface interface of sort package
type intSlice []int
func (s intSlice) Len() int { return len(s) }
func (s intSlice) Less(i, j int) bool { return s[i] < s[j] }
func (s intSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// f. Interface with struct
// i. Interface variable as struct field
type logger interface {
log(string)
}
type consoleLogger struct{}
func (consoleLogger) log(message string) {
fmt.Println("Log:", message)
}
// This is composition, not embedding. The service struct has a logger field,
// which means it "has-a" logger, but the logger is not part of the service's type.
// Composition allows the service to use the logger's functionality without inheriting its type.
type service struct {
logger logger // logger is a field of type logger
}
// ii. Embedding interface into the struct.
// This is embedding, not composition. The embeddedService struct "is-a" logger,
// because it includes the logger interface as part of its type.
type embeddedService struct {
logger
}
func main() {
// Using the existing bots
var e englishBot
s := spanishBot{}
g := germanBot{}
printGreeting(s)
printGreeting(e)
printGreeting(g)
// Using empty interface
printAnything(42)
printAnything("Hello")
printAnything(true)
// Using Stringer interface
p := person{name: "Alice", age: 30}
fmt.Println(p)
// Using sort.Interface
numbers := intSlice{3, 1, 4, 1, 5, 9, 2, 6, 5, 3}
fmt.Println("Before sorting:", numbers)
sort.Sort(numbers)
fmt.Println("After sorting:", numbers)
// Using interface as struct field
logger := consoleLogger{}
svc := service{logger: logger}
svc.logger.log("This is a log message")
// Using embedded interface
embeddedSvc := embeddedService{logger: logger}
embeddedSvc.log("This is an embedded log message")
}