LoginSignup
0
0

More than 1 year has passed since last update.

Golangでは暗黙的な型変換もあることを知ってた?

Posted at

環境

Go version: go1.17.8

コード

下記のコードにあるように、
明示的に変換しないとエラーになるタイプ (int) と
変換せずにそのまま代入できるタイプ (map[string]int) があることがわかります。

package main

import (
    "fmt"
    "runtime"
)

type MyInt int
type MyMap map[string]int

func main() {
    fmt.Printf("Go version: %s\n", runtime.Version())

    var x MyInt
    var y int
    x = y // コンパイルエラー: cannot use y (type int) as type MyInt in assignment

    var m1 MyMap
    var m2 map[string]int
    m1 = m2 //  OK
    m2 = m1 // OK
}

理由

Golang の仕様書の 代入可能性(Assignability) のところでちゃんと書いてありました。

x's type V and T have identical underlying types and at least one of V or T is not a defined type.

a と b が同一のunderlying type (基底型、背後霊的な型 w)を持ち、
a または b の少なくとも一方が defined type (派生型)でないなら、お互い代入可能のようです。
派生型は名前の通りで、別の型からtypeで新たに定義された方です。

そうすると、m1m2 はお互いに代入できることは明白ですが、

    var m1 MyMap
    var m2 map[string]int
    m1 = m2 //  OK
    m2 = m1 // OK
変数 基底型 派生型?
var m1 MyMap map[string]int Yes
var m2 map[string]int map[string]int No

問題はMyInt ですね。

    var x MyInt
    var y int
    x = y // コンパイルエラー: cannot use y (type int) as type MyInt in assignment
変数 基底型 派生型?
var x MyInt int Yes
var y int int No じゃなかった! ← ここ重要

int は 一見派生型じゃないように見えますが、
実は Golang の都合上、ソースコードにあるように、int も(自分自身の...)派生型になります。

type int int

ちなみに、上記のリンク先にあるように、
int以外にboolstring などの predeclared type が全て defined type (派生型)になるようです。

参考記事

入門 Go 言語仕様 Underlying Type / Go Language Underlying Type
惊了!原来 Go 语言也有隐式转型

元記事

Golangでは暗黙的な型変換もあることを知ってた?

Credits

Photo by Chinmay Bhattar

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0