はじめに
この記事ではGo言語でmath.Abs
を使う際に遭遇しがちなcannot use x (variable of type int) as float64 value in argument to math.Abs
というエラーの原因と対処法をまとめます。
Rubyなど、整数や小数を自動的に型変換してくれる言語に慣れていると、Go言語の型変換ルールに戸惑うかもしれません。
今回のエラーを解決しながら、Go言語の型付けを理解するきっかけにしていきましょう。
エラーの内容と原因
Go言語で整数型int
をそのままmath.Abs
に渡すと、次のエラーが出ます。
cannot use x (variable of type int) as float64 value in argument to math.Abs
たとえば以下のようなコードです。
package main
import (
"fmt"
"math"
)
func main() {
num1, num2 := -10, 5
x := num1 + num2
sum := math.Abs(x) // ここでエラーが発生
fmt.Println(sum)
}
これはmath.Abs
が引数としてfloat64
型を要求しているため、int
型であるx
をそのまま渡すと型が合わずコンパイルエラーになるのです。
解決策
大きく次の2つが考えられます。
1. float64へ型変換
以下のように明示的にfloat64
へ型変換すればエラーを解消できます。
package main
import (
"fmt"
"math"
)
func main() {
num1, num2 := -10, 5
x := num1 + num2
sum := math.Abs(float64(x)) // 引数を float64 型に変換
fmt.Println(sum)
}
上記のコードを実行すると問題なく5
が出力されます。
これでエラーは解消です。
2. math.Absを使わずif文で絶対値を求める(代替方法)
math.Abs
を使わずとも、条件分岐で絶対値を求めることも可能です。
package main
import (
"fmt"
)
func main() {
num1, num2 := -10, 5
x := num1 + num2
var sum int
if x < 0 {
// x がマイナスの場合は符号を反転
sum = -x
} else {
sum = x
}
fmt.Println(sum)
}
こちらでも問題なく5
が出力されます。
Go言語の型付けを深掘り
ここからは今回の問題に関連して、Goの型付けのルールをもう少し詳しく確認します。
エラーにならないケース
次のように-10 + 5
を引数として直接math.Abs
に渡した場合はコンパイルエラーになりません。
package main
import (
"fmt"
"math"
)
func main() {
// num1, num2 := -10, 5
// x := num1 + num2
sum := math.Abs(-10 + 5) // 変数を使わず引数として直接 -10 + 5 を渡す
fmt.Println(sum)
}
Goにおいて、-10 + 5
そのものは「型付けされていない定数(untyped constant) 」として扱われるからです。
型付けされていない定数
型付けされていない定数とは、「まだ具体的な型が確定してない状態の定数」を表す概念です。
※Goにおいて、定数とは単に「変化しない単純な値」のことを指します。
この型付けされていない定数は、使用される文脈に基づいて適切な型に変換されます。
今回の場合、sum := math.Abs(-10 + 5)
と書いた時に初めて-10 + 5
の型が確定します。
math.Abs
はfloat64
型を求めるため、-10 + 5
もfloat64
として解釈されるのです。
これは暗黙的な型変換とは異なり、Goの定数の型付けルールの一部です。
エラーになるケース
一方で、事前に変数へ代入してしまうとその時点で型がint
で確定します。
num1, num2 := -10, 5
x := num1 + num2 // x は int
このx
をmath.Abs
に渡そうとすると型がマッチせずコンパイルエラーを起こすのです。
変数に代入された時点で具体的な型(この場合はint
)が確定し、以降は他の型への自動変換は行われません。
そのため変数x
をmath.Abs
で使用する場合は、明示的にfloat64(x)
という型変換が必要になります。
まとめ
math.Abs
は引数にfloat64
型を求めるため、int
型の値を渡す場合は型変換が必要- Goにおいて型付けされていない定数は文脈に応じて適切な型に変換される
この記事のとおりに対応すればエラーは解消できるかなと思います。
後半のGoの型付けについてもこの機会に理解しておくと役立つ時があるはずです。
Rubyの場合、整数や小数を自動で型変換してくれるため、Go言語の学習においてはこの手のつまずきに今後も遭遇しそうです。
1つずつものにしていきましょう。
最後に、記事の内容に誤りがある場合、コメントにて教えていただけますと幸いです。
コメント