kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 その5 <fmt.Scanと変数宣言>

こんにちは、kurumi-bioです。5回目のブログです。
前回に引き続きGo言語について発信します。

 

環境

OSバージョン:Windows11 Home 22H2

Go言語のバージョン:go version go1.19.4 windows/amd64

初めに

今回は、fmtパッケージのScan関数について調べます。

fmt.Scan関数は、標準入力からテキストを読み込んで変数に格納します。
読み込むテキストは、スペースまたは改行で区切られます。

今まで気にしていなかったのですが、引数の数とエラー内容が戻り値として取得可能です。

変数宣言

標準入力から読み込んだ入力値を格納するための変数を宣言する必要があります。

変数宣言は、次の記載方法があります。

  1. var 変数名 変数型
  2. var 変数名 変数型 = 値(初期値)
  3. var 変数名 = 値(初期値) (※)値から型を推測するので変数型を省略
  4. 変数名 := 値(初期値)(※)varを省略

例)VarTest.go

package main
import "fmt"

func main() {
  var str1 string       // 1.の記載方法
  str1 = "A"            // 値を代入
  var str2 string = "A" // 2.の記載方法
  var str3 = "A"        // 3.の記載方法
  str4 := "A"           // 4.の記載方法

  fmt.Println(str1, str2, str3, str4)

}

実行結果は下記の通りです。全変数にAが代入されています。

fmt.Scan

では、実際にfmt.Scanの使用してみます。

変数型と代表的なstring,int,boolで宣言して動作を確認してみます。

例)ScanTest.go

package main
import "fmt"

func main() {
  var s string
  var i int
  var b bool

  fmt.Scan(&s)
  fmt.Println("s=",s)
  fmt.Scan(&i)
  fmt.Println("i=",i)
  fmt.Scan(&b)
  fmt.Println("b=",b)
}

まずは、変数型にあった値を入力してみます。

bool型以外は、入力値がそのまま出力されています。
ちなみにbool型に1を入力すると、trueになります。

さらにbool型はtrue/falseを入力することも可能です。

では、int形に文字列を入力してみます。

変数i(int型)は0と表示されて、変数b(bool型)は未入力ですがfalseと表示されます
なんとなく想像できるのですが、試しにint型にttrueと入力してみると、
下記のように変数b(bool型)は、trueと表示されます。
動きだけ見ると、int型は一文字だけ読み込んでいるように見えます。

戻り値

fmt.Scanの戻り値は、引数の数とエラー内容です。
引数の数の必要性がわからないのですが、動作を確認してみます。

例)ScanReturnTest.go

package main
import "fmt"

func main() {
  var i, j int

  n, err := fmt.Scan(&i,&j)
  if err != nil {
    fmt.Println("err=", err)
  } else {
    fmt.Printf("i=%d / j=%d / n=%d",i,j,n)
  }
}

実行すると下記の通り、変数nに引数の数が代入されています。


もう一つの戻り値のエラー内容ですが、先ほどのint型とbool型のプログラムで試してみます。(string型は動作確認で不要なので省略しています)
例)ScanTestK2.go

package main
import "fmt"

func main() {
  var i int
  var b bool

  _, err := fmt.Scan(&i)
  if err != nil {
    fmt.Println("err=", err)
  } else {
    fmt.Println("i=", i)
  }

  _, err2 := fmt.Scan(&b)
  if err2 != nil {
    fmt.Println("err2=", err2)
  } else {
    fmt.Println("b=", b)
  }
}


実行すると次の通りで、変数i(int型)で"expected integer"のエラーが発生しています。
おそらくttrueの最初のtを読み込んでエラーが発生し、
残りのテキスト(true)が変数b(bool型)に代入されたと思われます。

 

Go言語では、変数を宣言して使わないと
<変数名> declared but not used
というエラーになります。
例)ScanTestK1.go

package main
import "fmt"

func main() {
  var i int

  n, err := fmt.Scan(&i)
  if err != nil {
    fmt.Println("err=", err)
  } else {
    fmt.Println("i=", i)
  }
}


このエラーを回避するため、
ScanTestK2.goでは、_(アンダースコア変数)を使用して、
引数の数を受け取らないようにしています。

最後に

変数宣言を含めたため思っていたよりも長くなってしまいました。
初期値を記載すれば、型宣言が不要な点は今どきの言語かなと感じました。
また、":="の記載は使い勝手がよく、今後も多様すると思いました。