EX 3.10
练习 3.10: 编写一个非递归版本的comma函数,使用bytes.Buffer代替字符串链接操作。
func comma(s string) string {
var buf bytes.Buffern := len(s)fmt.Println(n)if n <= 3 {
return s}for i := n; i > 0; i-- {
if i%3 == 0 && i != n {
buf.WriteByte(',')}buf.WriteByte(s[n-i])}return buf.String()
}
EX 3.11
练习 3.11: 完善comma函数,以支持浮点数处理和一个可选的正负号的处理。
func comma(s string) string {
var buf bytes.BuffermantissaStart := 0if s[0] == '+' || s[0] == '-' {
buf.WriteByte(s[0])mantissaStart = 1}mantissaEnd := strings.Index(s, ".")if mantissaEnd == -1 {
mantissaEnd = len(s)}mantissa := s[mantissaStart:mantissaEnd]n := len(mantissa)if n <= 3 {
buf.WriteString(mantissa)} else {
for i := n; i > 0; i-- {
if i%3 == 0 && i != n {
buf.WriteByte(',')}buf.WriteByte(mantissa[n-i])}}buf.WriteString(s[mantissaEnd:])return buf.String()
}
EX 3.12
练习 3.12: 编写一个函数,判断两个字符串是否是相互打乱的,也就是说它们有着相同的字符,但是对应不同的顺序。
// 一
func isAnagram1(a, b string) bool {
j := 0for i := 0; i < len(a); i++ {
if strings.Count(a, a[i:i+1]) == strings.Count(b, a[i:i+1]) {
j++}}if !strings.EqualFold(a, b) && j == len(a) && len(a) == len(b) {
return true}return false
}// 二
func isAnagram2(a, b string) bool {
aFrep := make(map[rune]int)for _, c := range a {
aFrep[c]++}bFrep := make(map[rune]int)for _, c := range b {
bFrep[c]++}for k, v := range aFrep {
if bFrep[k] != v {
return false}}for k, v := range bFrep {
if aFrep[k] != v {
return false}}return true
}// 三
func isAnagram3(a, b string) bool {
aFrep := make(map[rune]int)for _, c := range a {
aFrep[c]++}bFrep := make(map[rune]int)for _, c := range b {
bFrep[c]++}if reflect.DeepEqual(aFrep, bFrep) {
return true}return false
}
EX 3.13
练习 3.13: 编写KB、MB的常量声明,然后扩展到YB。
const (KB = 1000MB = 1000 * KBGB = 1000 * MBPB = 1000 * GB
)
EX 7.1
练习 7.1: 使用来自ByteCounter的思路,实现一个针对单词和行数的计数器。你会发现bufio.ScanWords非常的有用。
type WordCounter intfunc (c *WordCounter) Write(p []byte) (int, error) {
scanner := bufio.NewScanner(bytes.NewReader(p))scanner.Split(bufio.ScanWords)for scanner.Scan() {
*c += WordCounter(1)}return 0, nil
}type LineCounter intfunc (c *LineCounter) Write(p []byte) (int, error) {
scanner := bufio.NewScanner(bytes.NewReader(p))scanner.Split(bufio.ScanLines)for scanner.Scan() {
*c += LineCounter(1)}return 0, nil
}
EX 7.2
练习 7.2: 写一个带有如下函数签名的函数CountingWriter,传入一个io.Writer接口类型,返回一个把原来的Writer封装在里面的新的Writer类型和一个表示新的写入字节数的int64类型指针。
type ByteCounter struct {
w io.Writerwritten int64
}func (c *ByteCounter) Write(p []byte) (int, error) {
n, err := c.w.Write(p)c.written += int64(n)return n, err
}func CountingWriter(w io.Writer) (io.Writer, *int64) {
c := ByteCounter{
w, 0}return &c, &c.written
}
EX 7.3
练习 7.3: 为在gopl.io/ch4/treesort (§4.4)中的*tree类型实现一个String方法去展示tree类型的值序列。
func (t *tree) String() string {
var s stringif t == nil {
return s}s += t.left.String()if t.left != nil {
s += ", "}s += strconv.Itoa(t.value)if t.right != nil {
s += ", "}s += t.right.String()return s
}
EX 7.7
练习 7.7: 解释为什么帮助信息在它的默认值是20.0没有包含°C的情况下输出了°C。
因为 CelsiusFlag 拥有 Celsius 作为成员,而 Celsius 实现了 String 方法(实现了 fmt.Stringer 接口),
所以打印是会通过 Celsius.String() 输出