8進数のエラーについて

2016/11/30

はじめに

Go言語を使っていたら見慣れないエラーが出てたので調べてみました。

エラーの内容

試験用にサンプルの日付データを作っていたら、以下のようなコンパイルエラーとなりました。

malformed octal constant
malformed integer constant: 08

エラーとなった原因のコードはこちらです。

t = time.Date(2016, time.Month(11), 08, 00, 00, 00, 00, time.Local)

原因

Go言語は先頭に0が付いた数値を8進数だと認識します。08は8進数としては存在しない値のためエラーとなってしまうのでした。同様に、09も同じエラーとなります。

対策

単純に対策をするのであれば、以下のように08から0を除いてしまえばエラーは解消されます。

t = time.Date(2016, time.Month(11), 8, 00, 00, 00, 00, time.Local)

どうしても0809と記載したい、そんなときには、数値を"で囲って文字列として指定しておき、文字列から数値に変換させれば大丈夫です。ただし、標準で用意されているstrconv.Atoi関数は2つの戻り値を返すので、そのままでは使えません。以下のように、変換用の関数を用意する必要があります。

package main

import (
	"fmt"
	"os"
	"strconv"
	"time"
)

func main() {
	t := time.Date(2016, time.Month(atoi("11")), atoi("08"), atoi("00"), atoi("00"), atoi("00"), atoi("00"), time.Local)
	fmt.Println(t)
}

func atoi(str string) int {
	num, err := strconv.Atoi(str)
	if err != nil {
		os.Exit(1)
	}
	return num
}

矩形選択を使用する場合など、桁数をあわせたい場合には使えるのかもしれません。別途関数を用意したり、パッケージを追加する必要があり少し面倒なので、他の解決策をご存じの方がいたらお教え下さい^^;

おわりに

見慣れないエラーで焦りましたが、原因がわかって一安心です。
これはGo言語に特有のエラーというわけではなく、他の言語で発生するようです。コマンドプロンプトで加算処理をする際に08を使用したら以下のようになりました。

C:\Users>SET /A 01+07
8
C:\Users>SET /A 01+08
無効な数字です。数値定数は 10 進 (17 桁)、16 進 (0x11 桁)、
または 8 進 (021 桁) です。
golang

再帰処理してみた

Go言語で構造体のスライスを扱ってみる