为什么我不能做fmt.Sprintf("%d.%d.%d.%d",a ...)?

Jan*_*iel 6 go

我正在学习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.我正在玩代码而且我粘贴了错误的输出.无论如何,感谢peterSO0x434D53关于Go中切片的不变性.

嗯,这提出了另一个问题.为什么以这种方式实施?我想你只是有一些Iterable接口,所以任何实现它的结构都会"正常工作".

旁注:当我第一次听说Go时,这个大胆的陈述"已编译,但富有表现力".显式接口实现就是这方面的一个很好的例子,但是显式转换,缺少运算符重载等等都给了我"90s Java感觉".这很难过,因为Go看起来很棒.

pet*_*rSO 8

围棋之旅

练习:Stringers

使IPAddr类型工具fmt.Stringer将地址打印为虚线四边形.

例如,IPAddr{1, 2, 3, 4}应打印为"1.2.3.4".

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)
  }
}
Run Code Online (Sandbox Code Playgroud)

没有隐式转换[]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)