You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An interface is a set of abstract methods, and can be implemented by non-interface types. It cannot therefore implement itself.
173
173
174
174
### Empty interface
175
175
176
176
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.
177
177
```Go
178
178
// define a as empty interface
179
-
varainterface{}
180
-
variint = 5
179
+
varvoidinterface{}
180
+
181
+
// vars
182
+
i:=5
181
183
s:="Hello world"
184
+
182
185
// a can store value of any type
183
-
a = i
184
-
a = s
186
+
void = i
187
+
void = s
185
188
```
189
+
186
190
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.
187
191
188
192
### Method arguments of an interface
189
193
190
194
Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function?
191
195
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.
193
197
```Go
194
198
typeStringerinterface {
195
199
String() string
196
200
}
197
-
```
201
+
```
198
202
This means any type that implements interface Stringer can be passed to fmt.Println as an argument. Let's prove it.
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.
225
229
```Go
226
230
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
227
231
fmt.Println("The biggest one is", boxes.BiggestsColor())
228
-
```
232
+
```
229
233
Attention: If the type implemented the interface `error`, fmt will call `Error()`, so you don't have to implement Stringer at this point.
230
234
231
235
### Type of variable in an interface
232
236
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.
234
238
235
239
- Assertion of Comma-ok pattern
236
240
@@ -284,7 +288,7 @@ It's quite easy to use this pattern, but if we have many types to test, we'd bet
284
288
- switch test
285
289
286
290
Let's use `switch` to rewrite the above example.
287
-
```Go
291
+
```Go
288
292
package main
289
293
290
294
import (
@@ -325,7 +329,7 @@ func main() {
325
329
}
326
330
327
331
```
328
-
332
+
329
333
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 .
330
334
331
335
### Embedded interfaces
@@ -351,38 +355,41 @@ type Interface interface {
351
355
// Swap swaps the elements with indexes i and j.
352
356
Swap(i, j int)
353
357
}
354
-
```
358
+
```
355
359
Another example is the `io.ReadWriter` in package `io`.
356
360
```Go
357
361
// io.ReadWriter
358
362
typeReadWriterinterface {
359
363
Reader
360
364
Writer
361
365
}
362
-
```
366
+
```
363
367
### Reflection
364
368
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.
366
370
367
371
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).
368
372
```Go
369
373
t:= reflect.TypeOf(i) // get meta-data in type i, and use t to get all elements
370
374
v:= reflect.ValueOf(i) // get actual value in type i, and use v to change its value
371
-
```
375
+
```
372
376
After that, we can convert the reflected types to get the values that we need.
373
377
```Go
374
378
varxfloat64 = 3.4
379
+
380
+
t:= reflect.TypeOf(x)
375
381
v:= reflect.ValueOf(x)
376
-
fmt.Println("type:", v.Type())
382
+
383
+
fmt.Println("type:", t)
384
+
fmt.Println("value:", v)
377
385
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
378
-
fmt.Println("value:", v.Float())
379
-
```
386
+
```
380
387
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.
381
388
```Go
382
389
varxfloat64 = 3.4
383
390
v:= reflect.ValueOf(x)
384
391
v.SetFloat(7.1)
385
-
```
392
+
```
386
393
Instead, we must use the following code to change the values from reflect types.
0 commit comments