是什么导致了这些Golang代码片段之间的结果差异?

e7arh2l6  于 2023-11-14  发布在  Go
关注(0)|答案(3)|浏览(140)

有谁知道为什么下面的两个Golang代码片段会得到不同的结果吗?在这两个应用程序中,String()方法构造了一个表示IPAddr中各个字节的字符串切片,然后使用strings.Join将它们连接成一个四点IP地址格式。但是,这两个应用程序对相同的输入产生不同的结果。注意这两个应用程序如何构造要在String()中连接的字符串切片的差异for循环中的方法。
应用1

package main

import (
    "fmt"
    "strconv"
    "strings"
)

type IPAddr [4]byte

func (ip IPAddr) String() string {
    s := make([]string, len(ip))
    for i := range ip {
        s[i] = strconv.Itoa(int(ip[i]))
    }
    return strings.Join(s, ".")
}

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

// Result:
// loopback: 127.0.0.1
// googleDNS: 8.8.8.8

字符集
应用二:

// Application 2

package main

import (
    "fmt"
    "strconv"
    "strings"
)

type IPAddr [4]byte

func (ip IPAddr) String() string {
    s := make([]string, len(ip))
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }
    return strings.Join(s, ".")
}

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

// Result:
// loopback: ....127.0.0.1
// googleDNS: ....8.8.8.8

ffvjumwh

ffvjumwh1#

在第二个String方法中...

func (ip IPAddr) String() string {
    s := make([]string, len(ip))
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }
    return strings.Join(s, ".")
}

字符集
.你从一个4字符串的切片开始。也就是说,在循环之前,s{"", "", "", ""}。对于循环的每次迭代,你都要向切片追加一个新项。如果我们在循环中添加一个fmt.Printf语句,如下所示:

for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
        fmt.Printf("s: %#v\n", s)
    }


我们看到输出:

s: []string{"", "", "", "", "127"}
s: []string{"", "", "", "", "127", "0"}
s: []string{"", "", "", "", "127", "0", "0"}
s: []string{"", "", "", "", "127", "0", "0", "1"}


当你在.上连接这段字符串时,你连接了8个项目。前四个是空的,这就是为什么你的结果以....开头。
如果你从一个空切片开始,你会得到你期望的结果:

func (ip IPAddr) String() string {
    s := []string{}
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }
    return strings.Join(s, ".")
}

7kjnsjlb

7kjnsjlb2#

第一个片段创建s,然后用字节的整数值的字符串表示来填充它的每个元素。

s := make([]string, len(ip))
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }

字符集
第二个代码片段也用len(ip)创建了s,但是它没有设置s[:len(ip)]中的一个,而是将 * 追加到那些原始的len(ip)上,导致s2xlen(ip)元素长,前半部分未设置。字符串的零值是"",所以在开头有额外的点。

s := make([]string, len(ip))
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }


The alternative to method one using append is to set the capacity, not the length, in make .

s := make([]string,0, len(ip))
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }

3df52oht

3df52oht3#

在第二种方法中

func (ip IPAddr) String() string {
    s := make([]string, len(ip))
    for _, val := range ip {
        s = append(s, strconv.Itoa(int(val)))
    }
    return strings.Join(s, ".")
}

字符集
你首先是making一个长度为len(ip)的数组,然后在它的末尾追加元素。所以它最终的长度为2*len(ip)

相关问题