Files
the-way-to-go_ZH_CN/eBook/11.11.md
ArkBriar 71ca328435 Add chapter 11.11: Printf and reflection
chmod -x 09.5.md 09.8.md
2015-10-25 01:13:11 +08:00

69 lines
2.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 11.11 Printf和反射
在Go语言的标准库中前几节所述的反射的功能被大量地使用。举个例子fmt包中的Printf(以及其他格式化输出函数)都会使用反射来分析它的`...`参数。
Printf的函数声明为
```go
func Printf(format string, args ... interface{}) (n int, err error)
```
Printf中的`...`参数为空接口类型。Printf使用反射包来解析这个参数列表。所以Printf能够知道它每个参数的类型。因此格式化字符串中只有%d而没有%u和%ld因为它知道这个参数是unsigned还是long。这也是为什么Print和Println在没有格式字符串的情况下还能如此漂亮地输出。
为了让大家更加具体地了解Printf中的反射我们实现了一个简单的通用输出函数。其中使用了type-switch来推导参数类型并根据类型来输出每个参数的值(这里用了10.7节中练习10.13的部分代码)
示例 11.15 print.go:
```go
// print.go
package main
import (
"os"
"strconv"
)
type Stringer interface {
String() string
}
type Celsius float64
func (c Celsius) String() string {
return strconv.FormatFloat(float64(c),'f', 1, 64) + " °C"
}
type Day int
var dayName = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
func (day Day) String() string {
return dayName[day]
}
func print(args ...interface{}) {
for i, arg := range args {
if i > 0 {os.Stdout.WriteString(" ")}
switch a := arg.(type) { // type switch
case Stringer: os.Stdout.WriteString(a.String())
case int: os.Stdout.WriteString(strconv.Itoa(a))
case string: os.Stdout.WriteString(a)
// more types
default: os.Stdout.WriteString("???")
}
}
}
func main() {
print(Day(1), "was", Celsius(18.36)) // Tuesday was 18.4 °C
}
// Tuesday was 18.4 °C
```
在12.8节中我们将阐释fmt.Fprintf()是怎么运用同样的反射原则的。
## 链接
- [目录](directory.md)
- 上一节:[反射包](11.10.md)
- 下一节:[接口和动态类型](11.12.md)