鍍金池/ 教程/ GO/ 10.7 類型的 String() 方法和格式化描述符
4.7 strings 和 strconv 包
13.6 啟動外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫
13 錯誤處理與測試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個例子:使用 Sorter 接口排序
?# 11.5 測試一個值是否實(shí)現(xiàn)了某個接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運(yùn)行時異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實(shí)例
12.8 使用接口的實(shí)際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說明
7.2 切片
8.0 Map
3.1 Go 開發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測試和基準(zhǔn)測試
6.8 閉包
4.9 指針
13.1 錯誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過 Git 打包和安裝
2.7 Go 運(yùn)行時(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動態(tài)類型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對調(diào)
6.11 計算函數(shù)執(zhí)行時間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開發(fā)環(huán)境與其它工具
13.8 測試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類型的切片
3.9 與其它語言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長參數(shù)
13.9 用(測試數(shù)據(jù))表驅(qū)動測試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫
3.3 調(diào)試器
4.5 基本類型和運(yùn)算符
?# 11.8 第二個例子:讀和寫
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項(xiàng)目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類型斷言:如何檢測和轉(zhuǎn)換接口變量的類型
5.4 for 結(jié)構(gòu)
4.8 時間和日期
2.3 在 Linux 上安裝 Go
12 讀寫數(shù)據(jù)
6.12 通過內(nèi)存緩存來提升性能
9.1 標(biāo)準(zhǔn)庫概述
12.6 用切片讀寫文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯誤的模式
3.2 編輯器和集成開發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測試多返回值函數(shù)的錯誤
6.7 將函數(shù)作為參數(shù)
8.2 測試鍵值對是否存在及刪除元素
3.4 構(gòu)建并運(yùn)行 Go 程序
2.1 平臺與架構(gòu)
5.3 switch 結(jié)構(gòu)

10.7 類型的 String() 方法和格式化描述符

當(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 類型,并為它定義一個 PushPop 方法,再為它定義 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),使它們更具有一般性。

鏈接