當(dāng)定義了一個有很多方法的類型時,十之八九你會使用 String()
方法來定制類型的字符串形式的輸出,換句話說:一種可閱讀性和打印性的輸出。如果類型定義了 String()
方法,它會被用在 fmt.Printf()
中生成默認(rèn)的輸出:等同于使用格式化描述符 %v
產(chǎn)生的輸出。還有 fmt.Print()
和 fmt.Println()
也會自動使用 String()
方法。
我們使用第 10.4 節(jié)中程序的類型來進(jìn)行測試:
示例 10.22 method_string.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}
當(dāng)你廣泛使用一個自定義類型時,最好為它定義 String()
方法。從上面的例子也可以看到,格式化描述符 %T
會給出類型的完全規(guī)格,%#v
會給出實(shí)例的完整輸出,包括它的字段(在程序自動生成 Go
代碼時也很有用)。
備注
不要在 String()
方法里面調(diào)用涉及 String()
方法的方法,它會導(dǎo)致意料之外的錯誤,比如下面的例子,它導(dǎo)致了一個無限遞歸調(diào)用(TT.String()
調(diào)用 fmt.Sprintf
,而 fmt.Sprintf
又會反過來調(diào)用 TT.String()
...),很快就會導(dǎo)致內(nèi)存溢出:
type TT float64
func (t TT) String() string {
return fmt.Sprintf("%v", t)
}
t.String()
練習(xí) 10.12 type_string.go
給定結(jié)構(gòu)體類型 T:
type T struct {
a int
b float32
c string
}
值 t
: t := &T{7, -2.35, "abc\tdef"}
。給 T 定義 String()
,使得 fmt.Printf("%v\n", t)
輸出:7 / -2.350000 / "abc\tdef"
。
練習(xí) 10.13 celsius.go
為 float64 定義一個別名類型 Celsius
,并給它定義 String()
,它輸出一個十進(jìn)制數(shù)和 °C 表示的溫度值。
練習(xí) 10.14 days.go
為 int 定義一個別名類型 Day
,定義一個字符串?dāng)?shù)組它包含一周七天的名字,為類型 Day
定義 String()
方法,它輸出星期幾的名字。使用 iota
定義一個枚舉常量用于表示一周的中每天(MO、TU...)。
練習(xí) 10.15 timezones.go
為 int 定義別名類型 TZ
,定義一些常量表示時區(qū),比如 UTC,定義一個 map,它將時區(qū)的縮寫映射為它的全稱,比如:UTC -> "Universal Greenwich time"
。為類型 TZ
定義 String()
方法,它輸出時區(qū)的全稱。
練習(xí) 10.16 stack_arr.go/stack_struct.go
實(shí)現(xiàn)棧(stack)數(shù)據(jù)結(jié)構(gòu):
它的格子包含數(shù)據(jù),比如整數(shù) i、j、k 和 l 等等,格子從底部(索引 0)至頂部(索引 n)來索引。這個例子中假定 n=3
,那么一共有 4 個格子。
一個新棧中所有格子的值都是 0。
push 將一個新值放到棧的最頂部一個非空(非零)的格子中。
pop 獲取棧的最頂部一個非空(非零)的格子的值。現(xiàn)在可以理解為什么棧是一個后進(jìn)先出(LIFO)的結(jié)構(gòu)了吧。
為棧定義一 Stack
類型,并為它定義一個 Push
和 Pop
方法,再為它定義 String()
方法(用于調(diào)試)它輸出棧的內(nèi)容,比如:[0:i] [1:j] [2:k] [3:l]
。
1)stack_arr.go:使用長度為 4 的 int 數(shù)組作為底層數(shù)據(jù)結(jié)構(gòu)。
2)stack_struct.go:使用包含一個索引和一個 int 數(shù)組的結(jié)構(gòu)體作為底層數(shù)據(jù)結(jié)構(gòu),索引表示第一個空閑的位置。
3)使用常量 LIMIT 代替上面表示元素個數(shù)的 4 重新實(shí)現(xiàn)上面的 1)和 2),使它們更具有一般性。