나는 몇 가지 코드를 작성하고 있으며 인수를 잡아서 전달하는 데 필요합니다 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 루프를 불필요하게 만들었더라도 컴파일러는이를 삽입해야합니다.
답변
인쇄하려는 문자열 조각 만 있으면 변환을 피하고 조인하여 정확히 동일한 출력을 얻을 수 있습니다.
package main
import (
"fmt"
"flag"
"strings"
)
func main() {
flag.Parse()
s := strings.Join(flag.Args(), " ")
fmt.Println(s)
}
답변
이 경우 형식 변환이 필요하지 않습니다. 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]
$
답변
Go에서 함수는 함수 정의의 매개 변수 목록에 지정된 유형의 인수 만받을 수 있습니다. 가변 매개 변수 언어 기능은이를 약간 복잡하게 만들지 만 잘 정의 된 규칙을 따릅니다.
의 함수 서명 fmt.Println
은 다음과 같습니다.
func Println(a ...interface{}) (n int, err error)
당 언어 specifiction ,
함수 시그니처의 최종 수신 매개 변수에는 … 접두사가 붙은 유형이있을 수 있습니다. 이러한 매개 변수가있는 함수를 가변이라고하며 해당 매개 변수에 대해 0 개 이상의 인수를 사용하여 호출 할 수 있습니다.
즉 Println
, interface{}
유형 의 인수 목록을 전달할 수 있습니다 . 모든 유형이 빈 인터페이스를 구현하므로 모든 유형의 인수 목록을 전달할 수 있습니다 Println(1, "one", true)
. 예를 들어 오류없이 를 호출 할 수 있습니다. 언어 사양의 “… 매개 변수에 인수 전달”섹션 을 참조하십시오 .
전달 된 값은 연속 요소가 실제 인수 인 새 기본 배열이있는 [] T 유형의 새 슬라이스이며, 모두 T에 할당 할 수 있어야합니다.
문제를 일으키는 부분은 사양에서 바로 그 직후입니다.
마지막 인수가 슬라이스 유형 [] T에 할당 될 수있는 경우 인수 다음에 …가 오면 … T 매개 변수의 값으로 변경되지 않고 전달 될 수 있습니다.이 경우 새 슬라이스가 작성되지 않습니다.
flag.Args()
유형 []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())
( fmt 패키지 문서에[elem0 elem1 ...]
따라 로 출력 됨 )
또는
fmt.Println(strings.Join(flag.Args(), ` `)
(각각 단일 공백으로 구분 된 문자열 슬라이스 요소를 출력합니다) 예를 들어 문자열 구분 기호가있는 문자열 패키지의 Join 함수를 사용 합니다 .
답변
리플렉션을 사용하는 것이 가능하다고 생각하지만 좋은 해결책인지 모르겠습니다
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)
}
산출:
$ go run .\main.go arg1 arg2
arg1,arg2
hello,world
1,2,3,4,5,6
{John 30},{Not John 20}
답변
fmt.Println
소요 가변 매개 변수를
func Println (a … interface {}) (n int, err 오류)
flag.Args()
변환없이 인쇄 가능[]interface{}
func main() {
flag.Parse()
fmt.Println(flag.Args())
}