👉A Tour of Go: Exercise: Stringers
I quite enjoyed this one, even though I still had to Google for some help. I got that I needed a function to implement the String()
method for IPAddr
(which is there in the help text too but I didn't notice, which goes to show I should spend longer reading the questions)
func (i IPAddr) String() string {
}
Within this I needed to take the four parts of the IP address and concatenate them with a .
separator. Feeling rather proud of myself I came up with this which nicely handled each part of the IP address:
func (i IPAddr) String() string {
a := ""
for v := range i {
a = a + v
}
return a
}
./prog.go:15:9: invalid operation: a + v (mismatched types string and int)
So let's try casting the type:
func (i IPAddr) String() string {
a := ""
for v := range i {
a = a + string(v)
}
return a
}
This executed successfully, but didn't work:
So let's add some debug:
func (i IPAddr) String() string {
a := ""
for v := range i {
fmt.Printf("Value: %v %vn", v, string(v))
a = a + string(v)
}
return a
}
Value:
Value:
Value:
Value:
loopback:
So the value is showing as empty, which is odd, because we know it's there. Let's try more debug:
func (i IPAddr) String() string {
a := ""
for v := range i {
fmt.Printf("value: %v tstring(value): %vn", v, string(v))
a = a + string(v)
}
return a
}
value: 0 string(value):
value: 1 string(value):
value: 2 string(value):
value: 3 string(value):
OK, so the value we're getting isn't the IP address pieces… because we made a mistake in the for
statement and we're getting the index, not the value. We're also getting a blank for the string, but we'll worry about that in a moment. Let's fix the for
statement first. Using the underscore we can ignore the index and store the actual value in v
:
func (i IPAddr) String() string {
a := ""
for _, v := range i {
fmt.Printf("value: %v tstring(value): %vn", v, string(v))
a = a + string(v)
}
value: 127 string(value):
value: 0 string(value):
value: 0 string(value):
value: 1 string(value):
We're getting somewhere.
What about this pesky blank string though when we try to cast the integer to a string? Courtesy of 6 Tips for Using Strings in Go and specifically the Convert ints (or any data type) into strings section I realised that string()
wasn't the way to do it. What string()
is doing is returning the ASCII character of the given value. Check out the output if I bump up the value in the string
value in the Printf
:
func (i IPAddr) String() string {
a := ""
for _, v := range i {
fmt.Printf("value: %v tstring(value+64): %vn", v, string(v+64))
a = a + string(v)
}
return a
}
value: 127 string(value+64): ¿
value: 0 string(value+64): @
value: 0 string(value+64): @
value: 1 string(value+64): A
Maybe this was mentioned in the Tour and I missed it, but in doing the type conversion I'd referred back to Type conversions and it's not covered there. So instead of string()
we can use strconv or Sprintf
:
func (i IPAddr) String() string {
a := ""
for _, v := range i {
fmt.Printf("value: %v tfmt.Sprintf(value): %vn", v, fmt.Sprintf("%d",v))
a = a + string(v)
}
return a
}
value: 127 fmt.Sprintf(value): 127
value: 0 fmt.Sprintf(value): 0
value: 0 fmt.Sprintf(value): 0
value: 1 fmt.Sprintf(value): 1
Now we're getting somewhere! Let's use this Sprintf
in building the a
variable too, and add in a .
in the format string:
func (i IPAddr) String() string {
a := ""
for _, v := range i {
a = a + fmt.Sprintf("%d.",v)
}
return a
}
Look at that! We're nearly there. Just the trailing .
to get rid of now, which a perusal of the strings
package turns up a function TrimRight
that should do the trick:
func (i IPAddr) String() string {
a := ""
for _, v := range i {
a = a + fmt.Sprintf("%d.",v)
}
return strings.TrimRight(a,".")
}
So the final code looks like this:
package main
import (
"fmt"
"strings"
)
type IPAddr [4]byte
func (i IPAddr) String() string {
a := ""
for _, v := range i {
a = a + fmt.Sprintf("%d.",v)
}
return strings.TrimRight(a,".")
}
func main() {
hosts := map[string]IPAddr{
"loopback": {127, 0, 0, 1},
"googleDNS": {8, 8, 8, 8},
}
for name, ip := range hosts {
fmt.Printf("%v: %vn", name, ip)
}
}
loopback: 127.0.0.1
googleDNS: 8.8.8.8
Top comments (0)