无法将[]字符串转换为[] interface {}

cru*_*izh 81 type-conversion go

我正在编写一些代码,我需要它来捕获参数并传递它们fmt.Println
(我希望它的默认行为,写入由空格分隔的参数,然后是换行符).但它需要[]interface {}flag.Args()返回一个[]string.
这是代码示例:

package main

import (
    "fmt"
    "flag"
)

func main() {
    flag.Parse()
    fmt.Println(flag.Args()...)
}
Run Code Online (Sandbox Code Playgroud)

这将返回以下错误:

./example.go:10: cannot use args (type []string) as type []interface {} in function argument
Run Code Online (Sandbox Code Playgroud)

这是一个错误吗?不应该fmt.Println采取任何阵列?顺便说一句,我也试过这样做:

var args = []interface{}(flag.Args())
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误:

cannot convert flag.Args() (type []string) to type []interface {}
Run Code Online (Sandbox Code Playgroud)

是否有"Go"方式解决此问题?

Ste*_*erg 98

这不是一个错误.fmt.Println()需要一种[]interface{}类型.这意味着,它必须是一片interface{}价值观,而不是"任何一片".要转换切片,您需要循环并复制每个元素.

old := flag.Args()
new := make([]interface{}, len(old))
for i, v := range old {
    new[i] = v
}
fmt.Println(new...)
Run Code Online (Sandbox Code Playgroud)

您不能使用任何切片的原因是a []string和a 之间的转换[]interface{}需要更改内存布局并在O(n)时间内发生.将类型转换为interface{}需要O(1)时间.如果他们不需要这个for循环,编译器仍然需要插入它.

  • 追加是神奇的.它内置并由语言专门处理.其他例子包括`new()`,`len()`和`copy()`.http://golang.org/ref/spec#Appending_and_copying_slices (4认同)
  • 顺便说一下,我在golang-nuts中找到了这个链接:https://groups.google.com/d/topic/golang-nuts/Il-tO1xtAyE/discussion (2认同)
  • 是的,每次迭代需要O(1)时间,循环需要O(n)时间.这就是我说的.对于接收`[] string`的函数,它需要一个`interface {}`.`interface {}`与`string`有不同的内存布局,因此需要转换每个元素的事实就是问题所在. (2认同)
  • @karlrh:不,假设 `Println` 函数修改了切片,并设置了一些元素(它没有,但假设它确实如此)。然后它可以将任何“interface{}”放入切片中,该切片应该只包含“string”。你真正想要的是像 Java 泛型通配符 `Slice<? extends []interface{}>`,但这在 Go 中不存在。 (2认同)
  • 更直接的文章 - > https://code.google.com/p/go-wiki/wiki/InterfaceSlice (2认同)

pet*_*rSO 10

在这种情况下,不需要类型转换.只需将flag.Args()值传递给fmt.Println.


题:

无法将[]字符串转换为[] interface {}

我正在编写一些代码,我需要它来捕获参数并通过fmt.Println传递它们(我想要它的默认行为,写入由空格分隔的参数,然后是换行符).

这是代码示例:

package main

import (
    "fmt"
    "flag"
)

func main() {
    flag.Parse()
    fmt.Println(flag.Args()...)
}
Run Code Online (Sandbox Code Playgroud)

包标志

import "flag"

func Args

func Args() []string

Args 返回非标志命令行参数.


包fmt

import "fmt"

功能Println

func Println(a ...interface{}) (n int, err error)

Println格式使用其操作数的默认格式并写入标准输出.始终在操作数之间添加空格,并附加换行符.它返回写入的字节数和遇到的任何写入错误.


在这种情况下,不需要类型转换.只需将flag.Args()值传递给fmt.Println,使用反射将值解释为类型[]string.Package reflect实现了运行时反射,允许程序操作具有任意类型的对象.例如,

args.go:

package main

import (
    "flag"
    "fmt"
)

func main() {
    flag.Parse()
    fmt.Println(flag.Args())
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ go build args.go
$ ./args arg0 arg1
[arg0 arg1]
$ 
Run Code Online (Sandbox Code Playgroud)


Mos*_*vah 9

如果它只是您想要打印的一小部分字符串,您可以通过加入来避免转换并获得完全相同的输出:

package main

import (
    "fmt"
    "flag"
    "strings"
)

func main() {
    flag.Parse()
    s := strings.Join(flag.Args(), " ")
    fmt.Println(s)
}
Run Code Online (Sandbox Code Playgroud)