Files
the-way-to-go_ZH_CN/eBook/11.11.md
Unknwon 45348b29ab 11.11
2015-10-31 15:38:25 -04:00

68 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](examples/chapter_11/print.go)
```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
}
```
在 12.8 节中我们将阐释 `fmt.Fprintf()` 是怎么运用同样的反射原则的。
## 链接
- [目录](directory.md)
- 上一节:[反射包](11.10.md)
- 下一节:[接口和动态类型](11.12.md)