不使用Sprintf实现Stringer接口的方法

huangapple go评论108阅读模式
英文:

Stringer implementation without using Sprintf

问题

我正在通过golang教程进行学习,但在其中一个练习中遇到了问题。我不确定为什么以下的String()函数不起作用:

  1. type IPAddr [4]byte
  2. func (addr IPAddr) String() string {
  3. return string(addr[0]) + "." + string(addr[1]) + "." + string(addr[2]) + "." + string(addr[3])
  4. }
  5. func main() {
  6. addrs := map[string]IPAddr{
  7. "loopback": {127, 0, 0, 1},
  8. "googleDNS": {8, 8, 8, 8},
  9. }
  10. for n, a := range addrs {
  11. fmt.Printf("%v: %v\n", n, a)
  12. }
  13. }

输出结果为:

  1. loopback: ...
  2. 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:

  1. type IPAddr [4]byte
  2. func (addr IPAddr) String() string {
  3. return string(addr[0]) + "." + string(addr[1]) + "." + string(addr[2]) + "." + string(addr[3])
  4. }
  5. func main() {
  6. addrs := map[string]IPAddr{
  7. "loopback": {127, 0, 0, 1},
  8. "googleDNS": {8, 8, 8, 8},
  9. }
  10. for n, a := range addrs {
  11. fmt.Printf("%v: %v\n", n, a)
  12. }
  13. }

Output:

  1. loopback: ...
  2. 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库将其格式化为字符串。

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. type IPAddr [4]byte
  7. func (addr IPAddr) String() string {
  8. return strconv.Itoa(int(addr[0])) + "." + strconv.Itoa(int(addr[1])) + "." + strconv.Itoa(int(addr[2])) + "." + strconv.Itoa(int(addr[3]))
  9. }
  10. func main() {
  11. addrs := map[string]IPAddr{
  12. "loopback": {127, 0, 0, 1},
  13. "googleDNS": {8, 8, 8, 8},
  14. }
  15. for n, a := range addrs {
  16. fmt.Printf("%v: %v\n", n, a)
  17. }
  18. }

输出:

  1. loopback: 127.0.0.1
  2. 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.

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. type IPAddr [4]byte
  7. func (addr IPAddr) String() string {
  8. return strconv.Itoa(int(addr[0])) + "." + strconv.Itoa(int(addr[1])) + "." + strconv.Itoa(int(addr[2])) + "." + strconv.Itoa(int(addr[3]))
  9. }
  10. func main() {
  11. addrs := map[string]IPAddr{
  12. "loopback": {127, 0, 0, 1},
  13. "googleDNS": {8, 8, 8, 8},
  14. }
  15. for n, a := range addrs {
  16. fmt.Printf("%v: %v\n", n, a)
  17. }
  18. }

Output:

  1. loopback: 127.0.0.1
  2. googleDNS: 8.8.8.8

答案2

得分: 0

一个更高效的实现,减少了临时内存分配:

  1. func (addr IPAddr) String() string {
  2. buf := make([]byte, 0, 3+1+3+1+3+1+3)
  3. return string(
  4. strconv.AppendInt(
  5. append(
  6. strconv.AppendInt(
  7. append(
  8. strconv.AppendInt(
  9. append(
  10. strconv.AppendInt(buf,
  11. int64(addr[0]), 10), '.'),
  12. int64(addr[1]), 10), '.'),
  13. int64(addr[2]), 10), '.'),
  14. int64(addr[3]), 10))
  15. }
英文:

A more efficient implementation with less temporary memory allocations:

  1. func (addr IPAddr) String() string {
  2. buf := make([]byte, 0, 3+1+3+1+3+1+3)
  3. return string(
  4. strconv.AppendInt(
  5. append(
  6. strconv.AppendInt(
  7. append(
  8. strconv.AppendInt(
  9. append(
  10. strconv.AppendInt(buf,
  11. int64(addr[0]), 10), '.'),
  12. int64(addr[1]), 10), '.'),
  13. int64(addr[2]), 10), '.'),
  14. int64(addr[3]), 10))
  15. }

huangapple
  • 本文由 发表于 2015年4月14日 04:55:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/29614943.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定