Files
the-way-to-go_ZH_CN/eBook/10.7.md
2015-08-13 15:41:43 +08:00

111 lines
3.9 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.

# 10.7 类型的String()方法和格式化描述符
当定义一个了有很多方法的类型时十之八九你会使用String()方法来定制类型的字符串形式的输出换句话说一种可阅读性和打印性的输出。如果类型定义了String()方法它会被用在fmt.Printf()中生成默认的输出:等同于使用格式化描述符%v产生的输出。还有fmt.Print()和fmt.Println()也会自动使用String()方法。
我们使用10.4中程序的类型来进行测试:
Listing 10.22—method_string.go:
```go
package main
import (
"fmt"
"strconv"
)
type TwoInts struct {
a int
b int
}
func main() {
two1 := new(TwoInts)
two1.a = 12
two1.b = 10
fmt.Printf("two1 is: %v\n", two1)
fmt.Println("two1 is:", two1)
fmt.Printf("two1 is: %T\n", two1)
fmt.Printf("two1 is: %#v\n", two1)
}
func (tn *TwoInts) String() string {
return "(" + strconv.Itoa(tn.a) + "/" + strconv.Itoa(tn.b) + ")"
}
```
输出:
two1 is: (12/10)
two1 is: (12/10)
two1 is: *main.TwoInts
two1 is: &main.TwoInts{a:12, b:10}
当你广泛使用一个自定义类型时最好为它定义String()方法。从上面的例子也可以看到,格式化描述符%T会给出类型的完全规格%#v会给出实例的完整输出包括它的字段在程序自动生成Go代码时也很有用
**备注:**
不要在String()方法里面调用涉及String()方法的方法它会导致意料之外的错误比如下面的例子它导致了一个无限迭代调用TT.String()调用fmt.Sprintf而fmt.Sprintf又会反过来调用TT.String()...),很快就会导致内存溢出:
```go
type TT float64
func (t TT) String() string {
return fmt.Sprintf("%v", s)
}
t. String()
```
**练习**
练习 10.12type_string.go
给定结构体类型T:
```go
type T struct {
a int
b float32
c string
}
```
值t: `t := &{7, -2.35, "abc\tdef"}`。给T定义String(),使得`fmt.Printf("%v\n", t)`输出:`7 / -2.350000 / "abc\tdef"`
练习 10.13celsius.go
为float64定义一个别名类型Celsius并给它定义String()它输出一个十进制数和°C表示的温度值。
练习 10.14days.go
为int定义一个别名类型Day定义一个字符串数组它包含一周七天的名字为类型Day定义String()方法它输出星期几的名字。使用iota定义一个枚举常量用于表示一周的中每天(MO,TU,...)
练习 10.15timezones.go
为int定义别名类型TZ定义一些常量表示时区比如UTC定义一个map它将时区的缩写映射为它的全称比如`UTC -> "Universal Greenwich time"`。为类型TZ定义String()方法,它输出时区的全称。
练习 10.16stack_arr.go / stack_struct.go
实现栈(stack)数据结构:
![](images/10.7_fig.jpg?raw=true)
它的格子包含数据比如整数ijkl等等格子从底部(索引0)之顶部(索引n)来索引。这个例子中假定n=3那么一共有4个格子。
一个新栈中所有格子的值都是0.
push将一个新值放到栈的最顶部一个非空非零的格子中。
pop获取栈的最顶部一个非空非零的格子的值。现在可以理解为什么栈是一个后进先出(LIFO)的结构了吧。
为栈定义一Stack类型并为它定义一个Push和Pop方法再为它定义String()方法(用于调试)它输出栈的内容,比如:`[0:i] [1:j] [2:k] [3:l]`
(1). stack_arr.go使用长度为4的int数据作为底层数据结构
(2). stack_struct.go使用包含一个索引和一个int数组的结构体作为底层数据结构所以表示第一个空闲的位置。
(3). 使用常量LIMIT代替上面表示元素个数的4重新实现上面的(1)和(2),是它们更具有一般性。
## 链接
- [目录](directory.md)
- 上一节:[10.6 方法](10.6.md)
- 下一节:[10.8 垃圾回收和SetFinalizer](10.8.md)