为了账号安全,请及时绑定邮箱和手机立即绑定

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

/ 猿问

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

Go
呼如林 2019-11-11 14:17:17

我正在编写一些代码,并且我需要它来捕获参数并将它们传递给fmt.Println

我(我想要它的默认行为,编写由空格分隔并由换行符分隔的参数)。但是它需要[]interface {}而flag.Args()返回[]string。

这是代码示例:


package main


import (

    "fmt"

    "flag"

)


func main() {

    flag.Parse()

    fmt.Println(flag.Args()...)

}

这将返回以下错误:


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

这是错误吗?不应该fmt.Println接受任何数组吗?顺便说一句,我也尝试这样做:


var args = []interface{}(flag.Args())

但我收到以下错误:


cannot convert flag.Args() (type []string) to type []interface {}

有“解决方案”解决此问题吗?


查看完整描述

3 回答

?
至尊宝的传说

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


old := flag.Args()

new := make([]interface{}, len(old))

for i, v := range old {

    new[i] = v

}

fmt.Println(new...)

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


查看完整回答
反对 回复 2019-11-11
?
米琪卡哇伊

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


题:


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


我正在编写一些代码,并且我需要它来捕获参数并将它们传递给fmt.Println(我希望它的默认行为是,编写用空格分隔并后跟换行符的参数)。


这是代码示例:


package main


import (

    "fmt"

    "flag"

)


func main() {

    flag.Parse()

    fmt.Println(flag.Args()...)

}

包装标志


import "flag"


功能Args


func Args() []string


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


软件包fmt


import "fmt"


功能印刷


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


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


在这种情况下,不需要类型转换。只需将flag.Args()值传递给即可fmt.Println,后者使用反射将值解释为类型[]string。包reflect实现了运行时反射,从而允许程序处理任意类型的对象。例如,


args.go:


package main


import (

    "flag"

    "fmt"

)


func main() {

    flag.Parse()

    fmt.Println(flag.Args())

}

输出:


$ go build args.go

$ ./args arg0 arg1

[arg0 arg1]


查看完整回答
反对 回复 2019-11-11
?
慕慕森

在Go中,函数只能接受函数定义的参数列表中指定的类型的参数。可变参数语言功能使这一点复杂化了一点,但它遵循明确定义的规则。


的功能签名为fmt.Println:


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

根据语言规范,


函数签名中的最终传入参数可以具有以...为前缀的类型。具有此类参数的函数称为可变参数(variadic),并且可以使用该参数的零个或多个参数来调用该函数。


这意味着您可以传递类型Println的参数列表interface{}。由于所有类型都实现了空接口,因此您可以传递任何类型的参数列表Println(1, "one", true),例如,这是您能够正确调用的方式。请参阅语言规范的“将参数传递给...参数”部分:


传递的值是[] T类型的新切片,带有新的基础数组,其后续元素是实际参数,所有参数都必须可分配给T。


说明书中紧随其后的是给您带来麻烦的部分:


如果最后一个参数可分配给切片类型[] T,则如果参数后面跟有...,则可以将其不变地作为... T参数的值传递。在这种情况下,不会创建新的切片。


flag.Args()是type []string。由于T在Println是interface{},[]T是[]interface{}。因此,问题在于字符串切片值是否可分配给接口切片类型的变量。通过尝试分配,您可以轻松地在go代码中对其进行测试,例如:


s := []string{}

var i []interface{}

i = s

如果您尝试进行此类分配,则编译器将输出以下错误消息:


cannot use s (type []string) as type []interface {} in assignment

因此,您不能在字符串切片之后使用省略号作为的参数fmt.Println。这不是错误,而是按预期工作。


您仍然可以flag.Args()使用多种方法进行打印Println,例如


fmt.Println(flag.Args())

([elem0 elem1 ...]根据fmt软件包说明文件,输出为)


要么


fmt.Println(strings.Join(flag.Args(), ` `)

(将输出字符串切片元素,每个字符串元素之间用一个空格隔开),例如,使用带有字符串分隔符的字符串包中的Join函数。


查看完整回答
反对 回复 2019-11-11

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信