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, 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.
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, a)
}
}
Output:
loopback: 127.0.0.1
googleDNS: 8.8.8.8
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))
}