[Go] 言語仕様書に出てくる型関連の用語まとめ
Golangの言語仕様書に登場する型関連の単語の関係について整理し、微妙な違いをわかりやすくするのがこの記事の目的です。
PredeclaredとComposite Type
Goの型は主に二つに類別できます[1]。
複合型は型リテラル(Type literal)(struct{...}
、interface{...}
、chan int
等)によって構成されます
// Predeclared type
int
bool
string
float32
// Composite type
struct{a, b int}
interface {}
chan int
[]string
[5]string
[int]string
Defined type
Goには型に新しい名前を付ける構文が二つあります。
type A string // type definition
type B = string // alias declaration
各構文によって作られた新しい型は次のようになります。
-
type definitionによって作られた新しい型
A
をdefined typeと言います。 -
alias declarationによって作られた新しい型
B
をstring
のaliasと言います。
事前宣言された型もここでtype definitionされているのでdefined type です[2] 。今後、type A string
のstring
にあたる型を参照した型と呼ぶことにします。
Defined typeでない型
Defined typeでない型は複合型です。a~eはDefined typeではありません[3]。
// 全てdefined type
var a strunct{a, b int}
var b interface{}
var c chan int
var d []string
var e [5]string
ここまでのDefined typeをまとめると次のようになります。
type A int // Aはdefined type、intはdefined type
type B []string // Bはdefined type、[]stringはdefined typeではない
type C = int // Cはdefined typeではない、intはdefined type
Underlying type
Underlying typeは型T
の基礎となる型のことで、演算や代入をした時の挙動に関わります。各型の挙動を表にまとめました。
Underlying type | |
---|---|
事前宣言された型 T
|
T 自身 |
型リテラルで構築される型 T
|
T 自身 |
alias T
|
参照した型と同じ |
defined type T
|
参照した型と同じ |
型に新しい名前を付けるための構文は2種類ありましたが、どちらもUnderlying typeを引き継ぎます。例えば、次のようになります。
int // intのunderlying typeはint
[]string // []stringのunderlying typeは[]string
type A int // Aのunderlying typeはint
type B []string // Bのunderlying typeは[]string
type C = int // Cのunderlying typeはint
Underlying typeに関しては、言語仕様書の次のリンク先の部分に詳しく書いてあります。
method set
- インターフェース型
T
のメソッドセットはそのインターフェース - それ以外の場合、型
T
に対して実装されたメソッドの集合
インターフェースを比較する時、method setは重要な概念になります。method setの例を次に挙げます。
package main
import (
"fmt"
)
type A interface {
foo()
bar()
}
type B interface {
hoge()
}
type MyInt int
func (i *MyInt) foo() {
fmt.Println("foo")
}
func (i *MyInt) bar() {
fmt.Println("bar")
}
func (i MyInt) hoge() {
fmt.Println("hoge")
}
/*
foo
bar
hoge
*/
func main() {
var x MyInt
x = 10
x.foo()
x.bar()
x.hoge()
}
- Aのmethod setは
foo
とbar
- Bのmethod setは
hoge
- MyIntのmethod setは
foo
とbar
とhoge
Untyped constant
Goの定数には型を明示するtyped constantと、型を明示しないuntyped constantがあります。
const a int = 10 // typed constant
const b = int(10) // typed constant
const a = 1000000 // untyped constant
untyped constant の利点は、整数定数や実数定数で本来は変数で表現できない値でも定数にできることです。また、nil
のようにあらゆる複合型として扱うことも可能です。ただし、変数に代入できなかったり、精度が落ちたりする場合があります。
package main
import "fmt"
func main() {
const a = 120
const a = 99999999999999999999999999999999
const b = 12e+1000000
const c = 3.14159265359
_ = int64(a) // NG
_ = float32(b) // NG
d := float32(c)
fmt.Println(d) // 3.1415927
}
untyped constantと言っても、完全に型がないわけではなく
The default type of an untyped constant is bool, rune, int, float64,complex128 or string respectively, depending on whether it is a boolean,rune, integer, floating-point, complex, or string constant.
とあるようにデフォルトの型(untyped numeric constant,untyped boolean constantなど)が存在しています。定数に関しては、言語仕様書の次のリンク先の部分に詳しく書いてあります。
加えた方が良い内容や記事内容に誤りあった場合、コメントで教えていただけると嬉しいです。
参考にさせていただいたサイト
-
便宜的にpredeclared typeと呼んでいますが、predeclared typeは言語仕様書には登場しない単語です。言語仕様書にはpredeclared boolean, numeric, or string typesと書いてあります。 ↩︎
-
なぜここのような定義がされているかは https://go.dev/ref/spec#Numeric_types に書いてあります。プラットフォームの差を吸収するためです。 ↩︎
-
ほとんどの構造体やインターフェースは、type.... で定義されていると思うのでdefined typeです。 ↩︎
Discussion