fmt.Scanln() を使用して stdin から読み取りたい 3 つの数値を含む行がありますが、このコードは機能しません。
X := make([]int, 3)
fmt.Scanln(X...)
fmt.Printf("%v\n", X)
次のエラー メッセージが表示されます。
cannot use X (type []int) as type []interface {} in function argument
理解できません。
fmt.Scanln() を使用して stdin から読み取りたい 3 つの数値を含む行がありますが、このコードは機能しません。
X := make([]int, 3)
fmt.Scanln(X...)
fmt.Printf("%v\n", X)
次のエラー メッセージが表示されます。
cannot use X (type []int) as type []interface {} in function argument
理解できません。
慣用的な Go は次のようになります。
func read(n int) ([]int, error) {
in := make([]int, n)
for i := range in {
_, err := fmt.Scan(&in[i])
if err != nil {
return in[:i], err
}
}
return in, nil
}
interface{}
何も意味しません。必要がない場合は使用しないでください。
例えば、
package main
import "fmt"
func intScanln(n int) ([]int, error) {
x := make([]int, n)
y := make([]interface{}, len(x))
for i := range x {
y[i] = &x[i]
}
n, err := fmt.Scanln(y...)
x = x[:n]
return x, err
}
func main() {
x, err := intScanln(3)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%v\n", x)
}
入力:
1 2 3
出力:
[1 2 3]
[]int
このエラー メッセージは、に変換する適切な方法がないために発生し[]interface{}
ます。これはスライスを参照していることに注意してください。したがって、使用している構文は正しいですがfmt.Scanln
、[]interface{}
. これは、 pkg 以外にも影響を与えfmt
ます。
これについて私が見た理由は、Goがメモリレイアウトを制御できるため、現在スライス変換を行う合理的な方法がないためです。これは、特定のタイプのスライスを期待する関数に渡す前に、手動で変換を行う必要があることを意味します。例えば:
package main
import (
"fmt"
)
func main() {
x := make([]int, 3)
y := make([]interface{}, 3)
y[0] = x[0]
y[1] = x[1]
y[2] = x[2]
fmt.Println(y...)
}
またはもう少し一般的なもの:
x := make([]int, 3)
y := make([]interface{}, len(x))
for i, v := range x {
y[i] = v
}
fmt.Println(y...)
特定の問題については、以下を参照してください。
x := make([]*int, 3)
for i := range x {
x[i] = new(int)
}
y := make([]interface{}, 3)
for i, v := range x {
y[i] = v
}
if _, err := fmt.Scanln(y...); err != nil {
fmt.Println("Scanln err: ", err)
}
for _, v := range y {
val := v.(*int)
fmt.Println(*val)
}
正しいバージョンは
X := make([]int, 3)
fmt.Scanln(&X[0], &X[1], &X[2])
fmt.Printf("%v\n", X)
コメントで、線の長さが異なる場合があると言っていました。その場合、独自のものを実装できますfmt.Scanner
:
package main
import (
"bytes"
"fmt"
)
type slice struct {
tok []int
}
func (s *slice) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool { return r != '\n' })
if err != nil { return err }
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
b := bytes.NewReader(tok)
for {
var d int
_, err := fmt.Fscan(b, &d)
if err != nil { break }
s.tok = append(s.tok, d)
}
return nil
}
func main() {
var s slice
fmt.Scan(&s)
fmt.Println(s.tok)
}