[] 문자열을 [] 인터페이스 {}로 변환 할 수 없습니다.
나는 몇 가지 코드를 작성하고 있으며 인수를 잡아서 전달하는 데 필요합니다 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 {}
이 문제를 해결할 수있는 "이동"방법이 있습니까?
이것은 버그가 아닙니다. 유형이 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 루프를 불필요하게 만들었더라도 컴파일러는이를 삽입해야합니다.
이 경우 형식 변환이 필요하지 않습니다. flag.Args()
값을에 전달하기 만하면 됩니다 fmt.Println
.
질문:
[] 문자열을 [] 인터페이스 {}로 변환 할 수 없습니다.
몇 가지 코드를 작성 중이며 인수를 잡아서 fmt.Println을 통해 전달하는 데 필요합니다 (기본 동작, 공백으로 구분 된 인수를 작성하고 그 뒤에 줄 바꿈이 이어짐).
다음은 코드 예입니다.
package main import ( "fmt" "flag" ) func main() { flag.Parse() fmt.Println(flag.Args()...) }
import "flag"
func Args() []string
Args
플래그가 아닌 명령 줄 인수를 반환합니다.
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]
$
인쇄하려는 문자열 조각 만 있으면 변환을 피하고 조인하여 정확히 동일한 출력을 얻을 수 있습니다.
package main
import (
"fmt"
"flag"
"strings"
)
func main() {
flag.Parse()
s := strings.Join(flag.Args(), " ")
fmt.Println(s)
}
Go에서 함수는 함수 정의의 매개 변수 목록에 지정된 유형의 인수 만받을 수 있습니다. 가변 매개 변수 언어 기능은이를 약간 복잡하게 만들지 만 잘 정의 된 규칙을 따릅니다.
에 대한 함수 서명 fmt.Println
은 다음과 같습니다.
func Println(a ...interface{}) (n int, err error)
당 언어 specifiction ,
함수 시그니처의 최종 수신 매개 변수에는 ... 접두사가 붙은 유형이있을 수 있습니다. 이러한 매개 변수가있는 함수를 가변이라고하며 해당 매개 변수에 대해 0 개 이상의 인수를 사용하여 호출 할 수 있습니다.
This means you can pass Println
a list of arguments of interface{}
type. Since all types implement the empty interface, you can pass a list of arguments of any type, which is how you're able to call Println(1, "one", true)
, for example, without error. See the "Passing arguments to ... parameters" section of the language specification:
the value passed is a new slice of type []T with a new underlying array whose successive elements are the actual arguments, which all must be assignable to T.
The part that's giving you trouble is right after that in the specification:
If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.
flag.Args()
is type []string
. Since T
in Println
is interface{}
, []T
is []interface{}
. So the question comes down to whether a string slice value is assignable to a variable of interface slice type. You can easily test that in your go code by attempting an assignment, for example:
s := []string{}
var i []interface{}
i = s
If you attempt such an assignment, the compiler will output this error message:
cannot use s (type []string) as type []interface {} in assignment
And that's why you can't use the ellipsis after a string slice as an argument to fmt.Println
. It's not a bug, it's working as intended.
There are still lots of ways you can print flag.Args()
with Println
, such as
fmt.Println(flag.Args())
(which will output as [elem0 elem1 ...]
, per fmt package documentation)
or
fmt.Println(strings.Join(flag.Args(), ` `)
(which will output the string slice elements, each separated by a single space) using the Join function in the strings package with a string separator, for example.
I think it's possible using reflection, but I don't know if it's a good solution
package main
import (
"fmt"
"reflect"
"strings"
)
type User struct {
Name string
Age byte
}
func main() {
flag.Parse()
fmt.Println(String(flag.Args()))
fmt.Println(String([]string{"hello", "world"}))
fmt.Println(String([]int{1, 2, 3, 4, 5, 6}))
u1, u2 := User{Name: "John", Age: 30},
User{Name: "Not John", Age: 20}
fmt.Println(String([]User{u1, u2}))
}
func String(v interface{}) string {
val := reflect.ValueOf(v)
if val.Kind() == reflect.Array || val.Kind() == reflect.Slice {
l := val.Len()
if l == 0 {
return ""
}
if l == 1 {
return fmt.Sprint(val.Index(0))
}
sb := strings.Builder{}
sb.Grow(l * 4)
sb.WriteString(fmt.Sprint(val.Index(0)))
for i := 1; i < l; i++ {
sb.WriteString(",")
sb.WriteString(fmt.Sprint(val.Index(i)))
}
return sb.String()
}
return fmt.Sprintln(v)
}
Output:
$ go run .\main.go arg1 arg2
arg1,arg2
hello,world
1,2,3,4,5,6
{John 30},{Not John 20}
fmt.Println
takes variadic parameter
func Println(a ...interface{}) (n int, err error)
Its possible to print flag.Args()
without converting into []interface{}
func main() {
flag.Parse()
fmt.Println(flag.Args())
}
참고URL : https://stackoverflow.com/questions/12990338/cannot-convert-string-to-interface
'program tip' 카테고리의 다른 글
목록의 요소 쌍 결합-Python (0) | 2020.10.08 |
---|---|
strict를 사용할 때 익명 함수에서 "this"가 정의되지 않은 이유는 무엇입니까? (0) | 2020.10.08 |
R에서 문자열-날짜 변환을위한 "표준 명확한 날짜"형식은 무엇입니까? (0) | 2020.10.08 |
XX 숨겨진 모듈이 웹팩의 의미 (0) | 2020.10.08 |
우선 순위 : ETag 또는 Last-Modified HTTP 헤더? (0) | 2020.10.08 |