Skip to content

Commit 8b46033

Browse files
committed
improving chapter 2.6
1 parent 367ff44 commit 8b46033

File tree

1 file changed

+57
-50
lines changed

1 file changed

+57
-50
lines changed

en/02.6.md

+57-50
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ This combination of methods is called an interface and is implemented by both St
2020

2121
An interface defines a set of methods, so if a type implements all the methods we say that it implements the interface.
2222
```Go
23-
2423
type Human struct {
2524
name string
2625
age int
@@ -39,6 +38,25 @@ type Employee struct {
3938
money float32
4039
}
4140

41+
// define interfaces
42+
type Men interface {
43+
SayHi()
44+
Sing(lyrics string)
45+
Guzzle(beerStein string)
46+
}
47+
48+
type YoungChap interface {
49+
SayHi()
50+
Sing(song string)
51+
BorrowMoney(amount float32)
52+
}
53+
54+
type ElderlyGent interface {
55+
SayHi()
56+
Sing(song string)
57+
SpendSalary(amount float32)
58+
}
59+
4260
func (h *Human) SayHi() {
4361
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
4462
}
@@ -51,7 +69,7 @@ func (h *Human) Guzzle(beerStein string) {
5169
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
5270
}
5371

54-
// Employee overloads Sayhi
72+
// Employee overloads SayHi
5573
func (e *Employee) SayHi() {
5674
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
5775
e.company, e.phone) //Yes you can split into 2 lines here.
@@ -64,26 +82,6 @@ func (s *Student) BorrowMoney(amount float32) {
6482
func (e *Employee) SpendSalary(amount float32) {
6583
e.money -= amount // More vodka please!!! Get me through the day!
6684
}
67-
68-
// define interface
69-
type Men interface {
70-
SayHi()
71-
Sing(lyrics string)
72-
Guzzle(beerStein string)
73-
}
74-
75-
type YoungChap interface {
76-
SayHi()
77-
Sing(song string)
78-
BorrowMoney(amount float32)
79-
}
80-
81-
type ElderlyGent interface {
82-
SayHi()
83-
Sing(song string)
84-
SpendSalary(amount float32)
85-
}
86-
8785
```
8886
We know that an interface can be implemented by any type, and one type can implement many interfaces simultaneously.
8987

@@ -117,25 +115,28 @@ type Employee struct {
117115
money float32
118116
}
119117

118+
// Interface Men implemented by Human, Student and Employee
119+
type Men interface {
120+
SayHi()
121+
Sing(lyrics string)
122+
}
123+
124+
// method
120125
func (h Human) SayHi() {
121126
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
122127
}
123128

129+
// method
124130
func (h Human) Sing(lyrics string) {
125131
fmt.Println("La la la la...", lyrics)
126132
}
127133

134+
// method
128135
func (e Employee) SayHi() {
129136
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
130137
e.company, e.phone) //Yes you can split into 2 lines here.
131138
}
132139

133-
// Interface Men implemented by Human, Student and Employee
134-
type Men interface {
135-
SayHi()
136-
Sing(lyrics string)
137-
}
138-
139140
func main() {
140141
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
141142
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
@@ -167,34 +168,37 @@ func main() {
167168
value.SayHi()
168169
}
169170
}
170-
171-
```
171+
```
172172
An interface is a set of abstract methods, and can be implemented by non-interface types. It cannot therefore implement itself.
173173

174174
### Empty interface
175175

176176
An empty interface is an interface that doesn't contain any methods, so all types implement an empty interface. This fact is very useful when we want to store all types at some point, and is similar to void* in C.
177177
```Go
178178
// define a as empty interface
179-
var a interface{}
180-
var i int = 5
179+
var void interface{}
180+
181+
// vars
182+
i := 5
181183
s := "Hello world"
184+
182185
// a can store value of any type
183-
a = i
184-
a = s
186+
void = i
187+
void = s
185188
```
189+
186190
If a function uses an empty interface as its argument type, it can accept any type; if a function uses empty interface as its return value type, it can return any type.
187191

188192
### Method arguments of an interface
189193

190194
Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function?
191195

192-
For example we use fmt.Println a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of fmt, we see the following definition.
196+
For example we use `fmt.Println` a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of `fmt`, we see the following definition.
193197
```Go
194198
type Stringer interface {
195199
String() string
196200
}
197-
```
201+
```
198202
This means any type that implements interface Stringer can be passed to fmt.Println as an argument. Let's prove it.
199203
```Go
200204
package main
@@ -210,7 +214,7 @@ type Human struct {
210214
phone string
211215
}
212216

213-
// Human implemented fmt.Stringer
217+
// Human implements fmt.Stringer
214218
func (h Human) String() string {
215219
return "Name:" + h.name + ", Age:" + strconv.Itoa(h.age) + " years, Contact:" + h.phone
216220
}
@@ -219,18 +223,18 @@ func main() {
219223
Bob := Human{"Bob", 39, "000-7777-XXX"}
220224
fmt.Println("This Human is : ", Bob)
221225
}
226+
```
222227

223-
```
224228
Looking back to the example of Box, you will find that Color implements interface Stringer as well, so we are able to customize the print format. If we don't implement this interface, fmt.Println prints the type with its default format.
225229
```Go
226230
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
227231
fmt.Println("The biggest one is", boxes.BiggestsColor())
228-
```
232+
```
229233
Attention: If the type implemented the interface `error`, fmt will call `Error()`, so you don't have to implement Stringer at this point.
230234

231235
### Type of variable in an interface
232236

233-
If a variable is the type that implements an interface, we know that any other type that implements the same interface can be assigned to this variable. The question is how can we know the specific type stored in the interface. There are two ways which I will show you.
237+
If a variable is the type that implements an interface, we know that any other type that implements the same interface can be assigned to this variable. The question is how can we know the specific type stored in the interface. There are two ways which I will show you.
234238

235239
- Assertion of Comma-ok pattern
236240

@@ -284,7 +288,7 @@ It's quite easy to use this pattern, but if we have many types to test, we'd bet
284288
- switch test
285289

286290
Let's use `switch` to rewrite the above example.
287-
```Go
291+
```Go
288292
package main
289293

290294
import (
@@ -325,7 +329,7 @@ func main() {
325329
}
326330

327331
```
328-
332+
329333
One thing you should remember is that `element.(type)` cannot be used outside of the `switch` body, which means in that case you have to use the `comma-ok` pattern .
330334

331335
### Embedded interfaces
@@ -351,38 +355,41 @@ type Interface interface {
351355
// Swap swaps the elements with indexes i and j.
352356
Swap(i, j int)
353357
}
354-
```
358+
```
355359
Another example is the `io.ReadWriter` in package `io`.
356360
```Go
357361
// io.ReadWriter
358362
type ReadWriter interface {
359363
Reader
360364
Writer
361365
}
362-
```
366+
```
363367
### Reflection
364368

365-
Reflection in Go is used for determining information at runtime. We use the `reflect` package, and this official [article](http://golang.org/doc/articles/laws_of_reflection.html) explains how reflect works in Go.
369+
Reflection in Go is used for determining information at runtime. We use the `reflect` package, and [The Laws of Reflection](http://golang.org/doc/articles/laws_of_reflection.html) post explains how reflect works in Go.
366370

367371
There are three steps involved when using reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation).
368372
```Go
369373
t := reflect.TypeOf(i) // get meta-data in type i, and use t to get all elements
370374
v := reflect.ValueOf(i) // get actual value in type i, and use v to change its value
371-
```
375+
```
372376
After that, we can convert the reflected types to get the values that we need.
373377
```Go
374378
var x float64 = 3.4
379+
380+
t := reflect.TypeOf(x)
375381
v := reflect.ValueOf(x)
376-
fmt.Println("type:", v.Type())
382+
383+
fmt.Println("type:", t)
384+
fmt.Println("value:", v)
377385
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
378-
fmt.Println("value:", v.Float())
379-
```
386+
```
380387
Finally, if we want to change the values of the reflected types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile.
381388
```Go
382389
var x float64 = 3.4
383390
v := reflect.ValueOf(x)
384391
v.SetFloat(7.1)
385-
```
392+
```
386393
Instead, we must use the following code to change the values from reflect types.
387394
```Go
388395
var x float64 = 3.4

0 commit comments

Comments
 (0)