Dragon Arrow written by Tatsuya Nakaji, all rights reserved animated-dragon-image-0164

go言語 型

updated on 2020-10-25

変数と型

  • どういう種類の値かを表すもの
    • 整数、浮動小数点数、真偽値、文字列 など
    • 自分で作ることも可能(ユーザ定義型)
  • 変数の型:どういう種類の値が入るのかを表したもの

動的型付け言語

  • プログラム実行時に型を検証する
  • 変数に型がなく、なんでも代入できる
  • php, python, ruby, javascript, Elixirなど

静的型付け言語

  • コンパイル時に型を検証する
  • 変数に型がある、型が違うと代入できない
  • C, C#, C++, java, go, typescriptなど


Goの利点

実行前に型の不一致を検出できる

  • コンパイルが通れば型の不一致が起きない
  • 型の不一致によるバグは見つけづらい問題

曖昧なものはエラーになる

  • 暗黙の型変換がない
    • 1 + "2" => "12"(JavaScript)
  • 浮動小数点数と整数の演算など見つけづらいバグが起きにくい

型推論がある

明示的に型を書く必要がない場合が多い


組み込み型

 

整数

int, int8, int16, int32, int64,

uint, uint8, uint16, uint32, uint64,

uintptr, byte, rune

浮動小数点数

float32, float64

複素数

complex64, complex128

文字列

string

真偽値

bool

エラー

error


型ごとの値の範囲


符号なし整数

型名説明範囲
uint88ビット符号なし整数0 ~ 255
uint1616ビット符号なし整数0 ~ 65535
uint3232ビット符号なし整数0 ~ 4294967295
uint6464ビット符号なし整数0 ~ 18446744073709551615
uint32ビットまたは64ビットの符号なし整数
(環境依存)
0 ~ 18446744073709551615

or

0 ~ 4294967295
uintptrポインタの値(環境依存)
byteuint8のエイリアス0 ~ 255


符号付き整数

型名説明範囲
int88ビット符号付き整数-128 ~ 127
int1616ビット符号付き整数-32768 ~ 32767
int3232ビット符号付き整数-2147483648 ~ 2147483647
int6464ビット符号付き整数-9223372036854775808 ~ 9223372036854775807
int32ビットまたは64ビットの符号付き整数
(環境依存)
-2147483648 ~ 2147483647

or

-9223372036854775808 ~ 9223372036854775807
runeint32のエイリアス-2147483648 ~ 2147483647


浮動小数点数

*int型はあるが、float型というのはない

型名説明
float3232ビット浮動小数点
float6464ビット浮動小数点


複素数

型名説明
complex64実数部・虚数部をfloat32で表現する複素数
complex128実数部・虚数部をfloat64で表現する複素数


uint8 

0 ~ 255 の整数を値に保存



型変換(キャスト)

Go 言語では暗黙的な型変換は許されていないため、下記のような異なる型の変数への代入はコンパイルエラーになる


var i int = 100
var f float64 = i  // cannot use i (type int) as type float64

このようなケースでは、下記のように明示的な型キャストを行う

var i int = 100
var f float64 = float64(i)  // OK

キャスト例 

intに変換

・int(値)

var i float64 = 100
var f int = int(i)  // OK

var i float64 = 66.6
var f int = int(i)  // 小数点は切り捨てられて、66になるので注意

var i float32 = 66.6
var f int = int(i)  // 小数点は切り捨てられて、66になるので注意

int32に変換

・int32(値)

var a uint8 = 100
var b uint32 = uint32(a) // OK

int8に変換

・int8(値)

var a uint32 = 1234567890
var b uint8 = uint8(a)
fmt.Println(b)  // 210(情報が欠落する) 0~255の場合しかuint8には正しくキャストできない

[]byteに変換

 ・[]byte(値)

var s string = "ABC"
var arr []byte = []byte(s)
fmt.Println(arr)  // [65 66 67]


stringに変換

・string(値)

arr := []byte{65, 66, 67}
s := string(arr)
fmt.Println(s)  // "ABC"



組み込み型 (真偽値)

型名説明
bool真(true)
または
偽(false)



package main
func main() {
    var a, b, c bool
    if a && b || !c {
        println("true")
    } else {
        println("false")
    }
}

上記コードでは、真偽の判定は以下のようになる

 

a

b

c

a && b

!c

a && b || !c

F

F

F

F

T

T

F

F

T

F

F

F

F

T

F

F

T

T

F

T

T

F

F

F

T

F

F

F

T

T

T

F

T

F

F

F

T

T

F

T

T

T

T

T

T

T

F

T



コンポジット型

複数のデータ型が集まって1つのデータ型になっている


型の種類

説明

構造体

型の異なるデータ型を集めたデータ型

配列

同じ型のデータを集めて並べたデータ型

スライス

配列の一部を切り出したデータ型

マップ

キーと値をマッピングさせたデータ型


コンポジット型のゼロ値

  • データの表現方法によって違う
    • 構造体や配列は要素(フィールド)がすべてゼロ値の値
    • スライスやマップはmakeなどで初期化が必要なためnilとなる

 

ゼロ値

構造体

フィールドがすべてゼロ値

配列

要素がすべてゼロ値

スライス

nil

マップ

nil


型リテラル

  • 型リテラルとは
    • 型の具体的な定義を書き下した型の表現方法
    • コンポジット型などを表現するために使う
    • 変数定義やユーザ定義型などで使用する

リテラル = 識別子(名前)が付与されてないもの


型を表すには名前をつけた型または型リテラル(名前のない型)で記述します。


名前をつけた型の例

type IntArray [16]int

type (
    Point struct{ x, y float64 }
    Polar Point
)

type TreeNode struct {
    left, right *TreeNode
    value *Comparable
}

type Block interface {
    BlockSize() int
    Encrypt(src, dst []byte)
    Decrypt(src, dst []byte)
}


型リテラルの例

// 配列型
[10]int

// 構造体型
struct {
    // フィールドリスト
}

// ポインタ型
*int

// 関数型
func(s string) int

// インタフェース型
interface {
    // メソッドリスト
}

// スライス型
[]int

// マップ型
map[string]int

// チャネル型
chan bool


構造体

  • 型の異なるデータ型の変数を集めたデータ構造
    • 各変数はフィールドと呼ばれる
      • 下の例では構造体pはフィールドnameとageを持つ
    • フィールドの型は異なってもよい(同じ型も可)
    • フィールドの型には組み込み型以外も使える
      • コンポジット型やユーザ定義型も使える


var p struct {
    name string
    age    int
}


構造体リテラル


フィールドを指定して初期化(構造体リテラル)



構造体リテラルの例

package main

import "fmt"
)
func main() {
    p := struct {
        name string
        age  int
    }{
        name: "Gopher",
        age:  10,
    }
    fmt.Println(p)
}

(コンソール出力)

{Gopher 10} 


名前をつけた構造体の例

package main

import "fmt"

func main() {
    type MyStrut struct {
        name string
        age  int
    }
    var p = MyStrut{name: "Gopher", age:  10}
    // もしくはこっちでも良い
    // p := MyStrut{name: "Gopher", age:  10}
    fmt.Println(p)
}

(コンソール出力)

{Gopher 10} 


フィールドの参照

package main

import "fmt"

func main() {
    p := struct {
        name string 
        age  int
        
    }{ 
        name: "Gopher", 
        age: 10,
    }
    p.age++ // p.age = p.age + 1と同じ
    fmt.Println(p.name, p.age)
}

(コンソール出力)

{Gopher 11}