我正在学习Go并且我坚持参加Go tour(exercise-stringer.go:https://tour.golang.org/methods/7).
这是一些代码:
type IPAddr [4]byte
// TODO: Add a "String() string" method to IPAddr.
func (a IPAddr) String() string {
return fmt.Sprintf("%d.%d.%d.%d", a...)
}
Run Code Online (Sandbox Code Playgroud)
所以我的内心表现IPAddr为[4]byte,所以传播运营商的作品.但是我得到了:
cannot use []string literal (type []string) as type []interface {} in argument to fmt.Sprintf
Run Code Online (Sandbox Code Playgroud)
有没有搞错?字符串切片也不起作用,这里发生了什么?
编辑:对不起,我的问题有一个错误 - 错误是关于类型IPAddr,而不是[]string.我正在玩代码而且我粘贴了错误的输出.无论如何,感谢peterSO和0x434D53关于Go中切片的不变性.
嗯,这提出了另一个问题.为什么以这种方式实施?我想你只是有一些Iterable接口,所以任何实现它的结构都会"正常工作".
旁注:当我第一次听说Go时,这个大胆的陈述"已编译,但富有表现力".显式接口实现就是这方面的一个很好的例子,但是显式转换,缺少运算符重载等等都给了我"90s Java感觉".这很难过,因为Go看起来很棒.
练习:Stringers
使
IPAddr类型工具fmt.Stringer将地址打印为虚线四边形.例如,
IPAddr{1, 2, 3, 4}应打印为"1.2.3.4".Run Code Online (Sandbox Code Playgroud)package main import "fmt" type IPAddr [4]byte // TODO: Add a "String() string" method to IPAddr. 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) } }
没有隐式转换[]string为[]interface {}.见转换中的围棋语言的编程规范.您需要提供显式转换.例如,
package main
import "fmt"
type IPAddr [4]byte
// A "String() string" method for IPAddr.
func (a IPAddr) String() string {
return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[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)
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
loopback: 127.0.0.1
googleDNS: 8.8.8.8
Run Code Online (Sandbox Code Playgroud)
小智 6
如 Go FAQ 部分中所述,我可以将 []T 转换为 []interface{},没有从类型化数组到 的隐式转换[]interface{}:
语言规范不允许这样做,因为这两种类型在内存中没有相同的表示。需要将元素单独复制到目标切片
以下解决方案有效,但需要创建一个中间切片:
func (ip IPAddr) String() string {
tmp := make([]interface{}, len(ip))
for i, val := range ip {
tmp[i] = val
}
return fmt.Sprintf("%d.%d.%d.%d", tmp...)
}
Run Code Online (Sandbox Code Playgroud)