英文:
Stringer implementation without using Sprintf
问题
我正在通过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()
可能是一个更好的解决方案,但我不确定为什么这个函数不起作用。
英文:
I am working through the golang tour and I am stuck in one of the exercises. I am not sure why the following does not work for a String() function:
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)
}
}
Output:
loopback: ...
googleDNS: ...
Granted that using fmt.Sprintf()
would be a nicer solution, but I'm not sure I understand why that function doesn't work.
答案1
得分: 7
这里发生的情况是,你直接将字节(例如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
英文:
What's happening there is that you're passing the byte e.g. 127 directly into string and expecting it to represent that byte as the integer 127 before converting it into a string. Instead what it's doing is interpreting it as a character with the byte value 127.
Instead you should convert that byte value into an integer, then use the strconv
library to format it as a string.
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)
}
}
Output:
loopback: 127.0.0.1
googleDNS: 8.8.8.8
答案2
得分: 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))
}
英文:
A more efficient implementation with less temporary memory allocations:
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))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论