15

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

理解できません。

4

5 に答える 5

13

慣用的な 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{}何も意味しません。必要がない場合は使用しないでください。

于 2015-11-19T18:33:38.507 に答える
9

例えば、

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]
于 2013-03-14T18:01:00.580 に答える
1

[]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)
    }
于 2013-03-14T16:19:44.340 に答える
1

正しいバージョンは

X := make([]int, 3)
fmt.Scanln(&X[0], &X[1], &X[2])
fmt.Printf("%v\n", X)
于 2013-03-14T16:01:27.357 に答える
0

コメントで、線の長さが異なる場合があると言っていました。その場合、独自のものを実装できます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)
}

https://golang.org/pkg/fmt#スキャナー

于 2021-05-27T18:20:17.940 に答える