Stringer实现不使用Sprintf

时间:2015-04-13 20:55:42

标签: go

我正在参加golang之旅,我被困在其中一个练习中。我不确定为什么以下内容对String()函数不起作用:

type IPAddr [4]byte

func (addr IPAddr) String() string {
    return string(addr[0]) + "." + string(addr[1]) + "." + string(addr[2]) + "." + string(addr[3])
}

func main() {
    addrs := map[string]IPAddr{
        "loopback":  {127, 0, 0, 1},
        "googleDNS": {8, 8, 8, 8},
    }
    for n, a := range addrs {
        fmt.Printf("%v: %v\n", n, a)
    }
}

输出:

loopback: ...
googleDNS: ...

当然,使用fmt.Sprintf()会是一个更好的解决方案,但我不确定我理解为什么该功能不起作用。

2 个答案:

答案 0 :(得分:6)

发生了什么事情,你正在传递这个字节,例如: 127直接进入字符串并期望它在将字节转换为字符串之前将该字节表示为整数127。相反,它正在做的是将其解释为字节值为127的字符。

相反,您应该将该字节值转换为整数,然后使用strconv库将其格式化为字符串。

package main

import (
    "fmt"
    "strconv"
)

type IPAddr [4]byte

func (addr IPAddr) String() string {
    return strconv.Itoa(int(addr[0])) + "." + strconv.Itoa(int(addr[1])) + "." + strconv.Itoa(int(addr[2])) + "." + strconv.Itoa(int(addr[3]))
}

func main() {
    addrs := map[string]IPAddr{
        "loopback":  {127, 0, 0, 1},
        "googleDNS": {8, 8, 8, 8},
    }
    for n, a := range addrs {
        fmt.Printf("%v: %v\n", n, a)
    }
}

输出:

loopback: 127.0.0.1
googleDNS: 8.8.8.8

答案 1 :(得分:0)

使用较少临时内存分配的更高效实现:

func (addr IPAddr) String() string {
    buf := make([]byte, 0, 3+1+3+1+3+1+3)
    return string(
        strconv.AppendInt(
            append(
                strconv.AppendInt(
                    append(
                        strconv.AppendInt(
                            append(
                                strconv.AppendInt(buf,
                                    int64(addr[0]), 10), '.'),
                            int64(addr[1]), 10), '.'),
                    int64(addr[2]), 10), '.'),
            int64(addr[3]), 10))
}