Ik ben het schrijven van een code, en ik heb het nodig om de argumenten op te vangen en door te geven door middel van fmt.Println
(Ik wil het standaard gedrag, om te schrijven argumenten gescheiden door spaties en gevolgd door een nieuwe regel). het duurt echter []interface {}
, maar flag.Args()
retourneert een []string
.
Hier is de code voorbeeld:
package main
import (
"fmt"
"flag"
)
func main() {
flag.Parse()
fmt.Println(flag.Args()...)
}
Dit keert terug de volgende foutmelding:
./example.go:10: cannot use args (type []string) as type []interface {} in function argument
Is dit een bug? Moet niet fmt.Println
neem geen reeks? By the way, ik heb ook geprobeerd om dit te doen:
var args = []interface{}(flag.Args())
maar ik krijg de volgende fout:
cannot convert flag.Args() (type []string) to type []interface {}
Is er een “Go” manier om dit?
workaround
1, Autoriteit 100%
Dit is geen bug. fmt.Println()
vereist []interface {}
type. Dat betekent, moet het een stukje van interface{}
waarden en niet “iedere slice” te zijn. Met het oog op het schijfje te zetten, moet u lus over en kopieer elk element.
old := flag.Args()
new := make([]interface{}, len(old))
for i, v := range old {
new[i] = v
}
fmt.Println(new...)
De reden dat je kunt elk stukje niet gebruiken, is dat conversie tussen een []string
en []interface {}
vereist het geheugen lay-out te worden veranderd en gebeurt op tijd binnen. Het omzetten van een soort van een interface{}
vereist O (1) tijd. Als ze dit maakte voor lus overbodig, zou de compiler nog steeds nodig om het in te voegen.
2, Autoriteit 10%
In dit geval is een typeconversie overbodig. Gewoon langs de flag.Args()
waarde fmt.Println
.
Vraag:
Kan niet converteren [] string op []-interface {}
Ik ben het schrijven van een code, en ik heb het nodig om de argumenten te vangen en doorgeven
ze door fmt.Println (ik wil het standaard gedrag, om te schrijven
argumenten gescheiden door spaties en gevolgd door een nieuwe regel).Hier is de code voorbeeld:
package main import ( "fmt" "flag" ) func main() { flag.Parse() fmt.Println(flag.Args()...) }
vlag Package
import "flag"
func Args() []string
Args
geeft de niet-flag command-line argumenten.
import "fmt"
func Println(a ...interface{}) (n int, err error)
Println
formats met behulp van de standaard formaten voor de operanden en
schrijft naar standaarduitvoer. Ruimten altijd toegevoegd tussen operanden
en een nieuwe regel wordt toegevoegd. Het geeft het aantal bytes geschreven en
elke afschrijving fout opgetreden.
In dit geval is een typeconversie overbodig. Gewoon langs de flag.Args()
waarde fmt.Println
, die reflectie gebruikt om de waarde als type []string
interpreteren. Pakket reflect
werktuigen run-time reflectie, waardoor een programma om objecten te manipuleren willekeurige types. Bijvoorbeeld,
args.go
package main
import (
"flag"
"fmt"
)
func main() {
flag.Parse()
fmt.Println(flag.Args())
}
Uitgang:
$ go build args.go
$ ./args arg0 arg1
[arg0 arg1]
$
3, Autoriteit 9%
Als het slechts een plakje snaren is die u wilt afdrukken, kunt u conversie vermijden en exact dezelfde uitvoer krijgen door lid te worden van:
package main
import (
"fmt"
"flag"
"strings"
)
func main() {
flag.Parse()
s := strings.Join(flag.Args(), " ")
fmt.Println(s)
}
4
Een andere optie is om het segment gewoon te herhalen:
package main
import "flag"
func main() {
flag.Parse()
for _, each := range flag.Args() {
println(each)
}
}
Antwoord 5
Ik denk dat het mogelijk is om reflectie te gebruiken, maar ik weet niet of het een goede oplossing is
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)
}
Uitvoer:
$ go run .\main.go arg1 arg2
arg1,arg2
hello,world
1,2,3,4,5,6
{John 30},{Not John 20}
Antwoord 6
fmt.Println
neemt variadic parameter
func Println(a …interface{}) (n int, err error)
Het is mogelijk om flag.Args()
af te drukken zonder te converteren naar een []interface{}
func main() {
flag.Parse()
fmt.Println(flag.Args())
}