序章

データ型は、プログラムを作成するときに特定の変数が格納する値の種類を指定します。 データ型は、データに対して実行できる操作も決定します。

この記事では、Goに固有の重要なデータ型について説明します。 これはデータ型の徹底的な調査ではありませんが、Goで使用できるオプションを理解するのに役立ちます。 いくつかの基本的なデータ型を理解すると、効率的に実行されるより明確なコードを記述できるようになります。

バックグラウンド

データ型について考える1つの方法は、現実の世界で使用するさまざまな種類のデータを検討することです。 実世界のデータの例は数値です。たとえば、整数(0、1、2、…)、整数(…、-1、0、1、…)、および無理数(π)を使用できます。

通常、数学では、さまざまな種類の数字を組み合わせて、ある種の答えを得ることができます。 たとえば、πに5を追加したい場合があります。

5 + π

無理数を説明するための答えとして方程式を保持するか、πを小数点以下の桁数が省略された数値に丸めてから、数値を合計することができます。

5 + π = 5 + 3.14 = 8.14 

しかし、単語などの別のデータ型を使用して数値を評価しようとすると、意味がなくなり始めます。 次の方程式をどのように解きますか?

shark + 8

コンピューターの場合、単語や数字など、各データ型はまったく異なります。 その結果、さまざまなデータ型を使用して値を割り当てる方法と、操作を通じてそれらを操作する方法に注意する必要があります。

整数

数学と同様に、コンピュータープログラミングの整数は、正、負、または0(…、-1、0、1、…)の整数です。 Goでは、整数は int. 他のプログラミング言語と同様に、4桁以上のコンマは使用しないでください。したがって、プログラムに1,000を書き込む場合は、次のように記述してください。 1000.

次のような簡単な方法で整数を出力できます。

fmt.Println(-459)
Output
-459

または、変数を宣言することもできます。この場合は、次のように、使用または操作している数値の記号です。

var absoluteZero int = -459
fmt.Println(absoluteZero)
Output
-459

Goでは整数を使って数学を行うこともできます。 次のコードブロックでは、 := 変数を宣言してインスタンス化する代入演算子 sum:

sum := 116 - 68
fmt.Println(sum)
Output
48

出力が示すように、数学演算子 - 整数を引いた 68 から 116、 その結果 48. 変数宣言の詳細については、変数のデータ型の宣言セクションを参照してください。

整数は、Goプログラム内でさまざまな方法で使用できます。 Goについて学び続けると、整数を操作し、このデータ型の知識に基づいて構築する多くの機会が得られます。

浮動小数点数

浮動小数点数または浮動小数点数は、整数として表現できない実数を表すために使用されます。 実数にはすべての有理数と無理数が含まれるため、浮動小数点数には9.0や-116.42などの小数部分を含めることができます。 Goプログラムでフロートを考えるために、小数点を含む数値です。

整数の場合と同様に、次のような簡単な方法で浮動小数点数を出力できます。

fmt.Println(-459.67)
Output
-459.67

次のように、floatを表す変数を宣言することもできます。

absoluteZero := -459.67
fmt.Println(absoluteZero)
Output
-459.67

整数の場合と同様に、Goでもfloatを使用して数学を行うことができます。

var sum = 564.0 + 365.24
fmt.Println(sum)
Output
929.24

整数と浮動小数点数の場合、3は整数を表し、3.0は浮動小数点を表すため、3≠3.0であることに注意することが重要です。

数値タイプのサイズ

整数と浮動小数点数の区別に加えて、Goには、サイズの静的または動的な性質によって区別される2種類の数値データがあります。 最初のタイプはアーキテクチャに依存しないタイプです。これは、コードが実行されているマシンに関係なく、ビット単位のデータのサイズが変更されないことを意味します。

今日のほとんどのシステムアーキテクチャは、32ビットまたは64ビットのいずれかです。 たとえば、オペレーティングシステムが64ビットアーキテクチャで実行されている最新のWindowsラップトップ用に開発している場合があります。 ただし、フィットネスウォッチなどのデバイス向けに開発している場合は、32ビットアーキテクチャを使用している可能性があります。 次のようなアーキテクチャに依存しないタイプを使用する場合 int32、コンパイルするアーキテクチャに関係なく、型のサイズは一定になります。

2番目のタイプは、実装固有のタイプです。 このタイプでは、ビットサイズは、プログラムが構築されているアーキテクチャに基づいて変化する可能性があります。 たとえば、 int タイプ、Goが32ビットアーキテクチャ用にコンパイルする場合、データタイプのサイズは32ビットになります。 プログラムが64ビットアーキテクチャ用にコンパイルされている場合、変数のサイズは64ビットになります。

サイズの異なるデータ型に加えて、整数などの型には、符号付き符号なしの2つの基本的な型もあります。 アン int8 は符号付き整数であり、-128〜127の値を持つことができます。 A uint8 は符号なし整数であり、0〜255の正の値のみを持つことができます。

範囲はビットサイズに基づいています。 バイナリデータの場合、8ビットは合計256の異なる値を表すことができます。 なぜなら int タイプは、正と負の両方の値、8ビット整数(int8)の範囲は-128〜127で、合計256の一意の可能な値になります。

Goには、アーキテクチャに依存しない次の整数型があります。

uint8       unsigned  8-bit integers (0 to 255)
uint16      unsigned 16-bit integers (0 to 65535)
uint32      unsigned 32-bit integers (0 to 4294967295)
uint64      unsigned 64-bit integers (0 to 18446744073709551615)
int8        signed  8-bit integers (-128 to 127)
int16       signed 16-bit integers (-32768 to 32767)
int32       signed 32-bit integers (-2147483648 to 2147483647)
int64       signed 64-bit integers (-9223372036854775808 to 9223372036854775807)

浮動小数点数と複素数もさまざまなサイズで提供されます。

float32     IEEE-754 32-bit floating-point numbers
float64     IEEE-754 64-bit floating-point numbers
complex64   complex numbers with float32 real and imaginary parts
complex128  complex numbers with float64 real and imaginary parts

特定のデータ型に有用な名前を割り当てるエイリアス番号タイプもいくつかあります。

byte        alias for uint8
rune        alias for int32

の目的 byte エイリアスは、プログラムがバイトデータ測定に関係のない小さな整数ではなく、文字列要素の一般的な計算測定としてバイトを使用している場合を明確にすることです。 それでも byteuint8 プログラムがコンパイルされると同じになります。 byte 文字データを数値形式で表すためによく使用されますが、 uint8 プログラム内の数字になることを目的としています。

The rune エイリアスは少し異なります。 どこ byteuint8 まったく同じデータであり、 rune 1バイトまたは4バイトにすることができ、範囲は次のように決定されます。 int32. A rune Unicode文字を表すために使用されますが、ASCII文字のみが int32 データ・タイプ。

さらに、Goには次の実装固有のタイプがあります。

uint     unsigned, either 32 or 64 bits
int      signed, either 32 or 64 bits
uintptr  unsigned integer large enough to store the uninterpreted bits of a pointer value 

実装固有のタイプのサイズは、プログラムがコンパイルされるアーキテクチャによって定義されます。

数値データ型の選択

正しいサイズを選択することは、通常、使用しているデータのサイズよりも、プログラミングしているターゲットアーキテクチャのパフォーマンスに関係があります。 ただし、プログラムのパフォーマンスの具体的な影響を知る必要はなく、最初に開始するときにこれらの基本的なガイドラインのいくつかに従うことができます。

この記事の前半で説明したように、アーキテクチャに依存しないタイプと実装固有のタイプがあります。 整数データの場合、Goでは次のような実装タイプを使用するのが一般的です。 int また uint それ以外の int64 また uint64. これにより、通常、ターゲットアーキテクチャの処理速度が最速になります。 たとえば、 int64 32ビットアーキテクチャにコンパイルすると、アーキテクチャ間でデータを移動するために追加のCPUサイクルが必要になるのに比べて、これらの値の処理に少なくとも2倍の時間がかかります。 使用した場合 int 代わりに、プログラムはそれを32ビットアーキテクチャの32ビットサイズとして定義し、処理が大幅に高速化されます。

特定のサイズ範囲を超えないことがわかっている場合は、アーキテクチャに依存しないタイプを選択すると、速度が向上し、メモリ使用量が減少する可能性があります。 たとえば、データが次の値を超えないことがわかっている場合 100、および正の数のみになり、次に uint8 必要なメモリが少なくなるため、プログラムがより効率的になります。

数値データ型の可能な範囲のいくつかを見てきたので、プログラムでそれらの範囲を超えた場合に何が起こるかを見てみましょう。

オーバーフロー対。 包み込む

Goは、値がで計算されるかどうかに応じて、格納するように設計されたデータ型よりも大きい値を格納しようとすると、数値のオーバーフローと数値のラップアラウンドの両方を行う可能性があります。コンパイル時または実行時。 コンパイル時エラーは、プログラムがプログラムをビルドしようとしたときにエラーを検出したときに発生します。 プログラムのコンパイル後、実際に実行中にランタイムエラーが発生します。

次の例では、 maxUint32 最大値まで:

package main

import "fmt"

func main() {
	var maxUint32 uint32 = 4294967295 // Max uint32 size
	fmt.Println(maxUint32)
}

コンパイルして実行すると、次の結果が得られます。

Output
4294967295

追加すると 1 実行時の値にラップアラウンドします 0:

Output
0

一方、追加するプログラムを変更しましょう 1 変数を割り当てるとき、コンパイル時の前に:

package main

import "fmt"

func main() {
	var maxUint32 uint32 = 4294967295 + 1
	fmt.Println(maxUint32)

}

コンパイル時に、コンパイラーが値が大きすぎて指定されたデータ型を保持できないと判断できる場合、コンパイラーは overflow エラー。 これは、計算された値が指定したデータ型に対して大きすぎることを意味します。

コンパイラは値をオーバーフローさせると判断できるため、エラーがスローされます。

Output
prog.go:6:36: constant 4294967296 overflows uint32

データの境界を理解することは、将来のプログラムの潜在的なバグを回避するのに役立ちます。

数値型について説明したので、ブール値を格納する方法を見てみましょう。

ブール値

boolean データ型は、次の2つの値のいずれかになります。 true また false、およびとして定義されます bool データ型として宣言する場合。 ブール値は、数学の論理ブランチに関連付けられている真理値を表すために使用されます。これは、コンピューターサイエンスのアルゴリズムに情報を提供します。

その価値 truefalse 常に小文字になります tf それぞれ、Goで事前に宣言された識別子であるため。

数学の多くの演算は、真または偽のいずれかに評価される答えを私たちに与えます。

  • より大きい
    • 500> 100 true
    • 1> 5 false
  • 未満
    • 200 <400 true
    • 4 <2 false
  • 同等
    • 5=5真
    • 500 = 400 false

数値と同様に、ブール値を変数に格納できます。

myBool := 5 > 8

次に、を呼び出してブール値を出力できます。 fmt.Println() 関数:

fmt.Println(myBool)

以来 5 より大きいではありません 8、次の出力を受け取ります。

Output
false

Goでより多くのプログラムを作成するにつれて、ブール値がどのように機能するか、およびさまざまな関数と操作がどちらに評価されるかについて、よりよく理解できるようになります。 true また false プログラムのコースを変更することができます。

文字列

文字列は、定数または変数のいずれかである1つ以上の文字(文字、数字、記号)のシーケンスです。 文字列はいずれかのバッククォート内に存在します ` または二重引用符 " Goで、使用する引用符に応じて異なる特性があります。

逆引用符を使用すると、raw文字列リテラルが作成されます。 二重引用符を使用すると、解釈された文字列リテラルが作成されます。

生の文字列リテラル

生の文字列リテラルは、バッククォート間の文字シーケンスであり、バックティックと呼ばれることがよくあります。 引用符内では、後引用符自体を除いて、すべての文字が後引用符の間に表示されるのと同じように表示されます。

a := `Say "hello" to Go!`
fmt.Println(a)
Output
Say "hello" to Go!

通常、バックスラッシュは文字列内の特殊文字を表すために使用されます。 たとえば、解釈された文字列では、 \n 文字列の改行を表します。 ただし、バックスラッシュは生の文字列リテラル内では特別な意味はありません。

a := `Say "hello" to Go!\n`
fmt.Println(a)

バックスラッシュは文字列リテラルでは特別な意味を持たないため、実際には次の値を出力します。 \n 新しい行を作成する代わりに:

Output
Say "hello" to Go!\n

生の文字列リテラルを使用して、複数行の文字列を作成することもできます。

a := `This string is on 
multiple lines
within a single back 
quote on either side.`
fmt.Println(a)
Output
This string is on multiple lines within a single back quote on either side.

上記のコードブロックでは、新しい行は文字通り入力から出力に引き継がれていました。

解釈された文字列リテラル

解釈される文字列リテラルは、次のように、二重引用符で囲まれた文字シーケンスです。 "bar". 引用符内には、改行とエスケープされていない二重引用符を除く任意の文字が表示される場合があります。 解釈された文字列に二重引用符を表示するには、次のようにバックスラッシュをエスケープ文字として使用できます。

a := "Say \"hello\" to Go!"
fmt.Println(a)
Output
Say "hello" to Go!

ほとんどの場合、解釈された文字列リテラルを使用します。これは、文字列内でエスケープ文字を使用できるためです。 文字列の操作の詳細については、Goでの文字列の操作の概要をご覧ください。

UTF-8文字を含む文字列

UTF-8は、可変幅の文字を1〜4バイトにエンコードするために使用されるエンコード方式です。 Goは、特別なセットアップ、ライブラリ、またはパッケージなしで、すぐに使用できるUTF-8文字をサポートします。 文字などのローマ字 A 数値65などのASCII値で表すことができます。 ただし、の国際文字などの特殊文字を使用する 、UTF-8が必要になります。 Goは rune UTF-8データのエイリアスタイプ。

a := "Hello, 世界"

あなたは使用することができます range のキーワード for Goの任意の文字列、さらにはUTF-8文字列を介してインデックスを作成するためのループ。 for ループと range シリーズの後半でさらに詳しく説明します。 今のところ、これを使用して特定の文字列のバイト数をカウントできることを知っておくことが重要です。

package main

import "fmt"

func main() {
	a := "Hello, 世界"
	for i, c := range a {
		fmt.Printf("%d: %s\n", i, string(c))
	}
	fmt.Println("length of 'Hello, 世界': ", len(a))
}

上記のコードブロックでは、変数を宣言しました a の値を割り当てました Hello, 世界 それに。 割り当てられたテキストには、UTF-8文字が含まれています。

次に、標準を使用しました for ループと同様に range キーワード。 Goでは、 range キーワードは、一度に1文字を返す文字列と、文字が文字列内にあるバイトインデックスを介してインデックスを作成します。

を使用して fmt.Printf 関数、私たちはのフォーマット文字列を提供しました %d: %s\n. %d は数字(この場合は整数)の出力動詞であり、 %s 文字列の出力動詞です。 次に、の値を提供しました i、これはの現在のインデックスです for ループ、および c、これはの現在の文字です for ループ。

最後に、変数の全長を出力しました a ビルトインを使用して len 関数。

先ほど、ルーンはのエイリアスであると述べました int32 1〜4バイトで構成できます。 The 文字の定義には3バイトかかり、UTF-8文字列を介して範囲を指定すると、それに応じてインデックスが移動します。 これが理由です i 印刷時にシーケンシャルではありません。

Output
0: H 1: e 2: l 3: l 4: o 5: , 6: 7: 世 10: 界 length of 'Hello, 世界': 13

ご覧のとおり、長さは文字列全体に及ぶのにかかった回数よりも長くなっています。

常にUTF-8文字列を使用しているとは限りませんが、使用している場合は、それらが単一ではなくルーン文字である理由を理解できます。 int32.

変数のデータ型の宣言

さまざまなプリミティブデータ型について理解したので、これらの型をGoの変数に割り当てる方法について説明します。

Goでは、キーワードを使用して変数を定義できます var その後に、変数の名前と必要なデータ型が続きます。

次の例では、という変数を宣言します pi タイプの float64.

キーワード var 宣言された最初のものです:

var pi float64

変数の名前が続き、 pi:

var pi float64

そして最後にデータ型 float64:

var pi float64

オプションで、次のような初期値も指定できます。 3.14:

var pi float64 = 3.14

Goは静的に型付けされた言語です。 静的に型付けされるということは、プログラム内の各ステートメントがコンパイル時にチェックされることを意味します。 また、データ型が変数にバインドされているのに対し、動的にリンクされた言語では、データ型が値にバインドされていることも意味します。

たとえば、Goでは、変数を宣言するときに型が宣言されます。

var pi float64 = 3.14
var week int = 7

これらの変数を異なる方法で宣言した場合、これらの各変数は異なるデータ型になる可能性があります。

これは、データ型が値に関連付けられているPHPのような言語とは異なります。

$s = "sammy";         // $s is automatically a string
$s = 123;             // $s is automatically an integer

上記のコードブロックでは、最初の $s 値が割り当てられているため、文字列です "sammy"、および2番目は、値があるため整数です。 123.

次に、配列などのより複雑なデータ型を見てみましょう。

配列

array は、要素の順序付けられたシーケンスです。 アレイの容量は、作成時に定義されます。 配列がそのサイズを割り当てると、サイズは変更できなくなります。 配列のサイズは静的であるため、メモリを1回だけ割り当てることを意味します。 これにより、配列の操作が多少難しくなりますが、プログラムのパフォーマンスが向上します。 このため、配列は通常、プログラムを最適化するときに使用されます。 次に説明するスライスは、より柔軟性があり、他の言語の配列と考えるものを構成します。

配列は、配列のサイズを宣言し、次に中括弧で囲まれた値でデータ型を宣言することによって定義されます。 { }.

文字列の配列は次のようになります。

[3]string{"blue coral", "staghorn coral", "pillar coral"}

配列を変数に格納して出力できます。

coral := [3]string{"blue coral", "staghorn coral", "pillar coral"}
fmt.Println(coral)
Output
[blue coral staghorn coral pillar coral]

前述のように、スライスは配列に似ていますが、はるかに柔軟性があります。 この可変データ型を見てみましょう。

スライス

スライスは、長さが変化する可能性のある要素の順序付けられたシーケンスです。 スライスは動的にサイズを大きくすることができます。 スライスに新しいアイテムを追加するときに、スライスに新しいアイテムを格納するのに十分なメモリがない場合、必要に応じてシステムからより多くのメモリを要求します。 スライスは必要に応じて要素を追加するために拡張できるため、配列よりも一般的に使用されます。

スライスは、開始および終了の角括弧が前に付いたデータ型を宣言することによって定義されます [] 中括弧の間に値があります { } .

整数のスライスは次のようになります。

[]int{-3, -2, -1, 0, 1, 2, 3}

フロートのスライスは次のようになります。

[]float64{3.14, 9.23, 111.11, 312.12, 1.05}

文字列のスライスは次のようになります。

[]string{"shark", "cuttlefish", "squid", "mantis shrimp"}

文字列のスライスを次のように定義しましょう seaCreatures:

seaCreatures := []string{"shark", "cuttlefish", "squid", "mantis shrimp"}

変数を呼び出すことで、それらを出力できます。

fmt.Println(seaCreatures)

出力は、作成したリストとまったく同じになります。

Output
[shark cuttlefish squid mantis shrimp]

使用できます append スライスにアイテムを追加するキーワード。 次のコマンドは、の文字列値を追加します seahorse スライスに:

seaCreatures = append(seaCreatures, "seahorse")

印刷することで、追加されたことを確認できます。

fmt.Println(seaCreatures)
Output
[shark cuttlefish squid mantis shrimp seahorse]

ご覧のとおり、未知のサイズの要素を管理する必要がある場合、スライスは配列よりもはるかに用途が広いでしょう。

マップ

map は、Goの組み込みハッシュまたは辞書タイプです。 マップは、キーをペアとして使用してデータを保存します。 これは、インデックス(この場合はキー)で値をすばやく検索するプログラミングに役立ちます。 たとえば、ユーザーIDで索引付けされたユーザーのマップを保持したい場合があります。 キーはユーザーIDであり、ユーザーオブジェクトは値です。 キーワードを使用して地図を作成します map 角かっこで囲まれたキーデータ型が続きます [ ]、その後に中括弧で囲まれた値のデータ型とキーと値のペアが続きます。

map[key]value{}

通常、IDに含まれる情報など、関連するデータを保持するために使用されるマップは、次のようになります。

map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

中括弧に加えて、マップ全体にコロンもあります。 コロンの左側の単語がキーです。 キーは、Goの比較可能なタイプであればどれでもかまいません。 比較可能な型は、次のようなプリミティブ型です。 strings, ints、など。 プリミティブ型は言語によって定義され、他の型を組み合わせて構築されたものではありません。 これらはユーザー定義の型にすることができますが、プログラミングエラーを回避するために、単純に保つことをお勧めします。 上記の辞書のキーは次のとおりです。 name, animal, color、 と location.

コロンの右側の単語は値です。 値は任意のデータ型で構成できます。 上記の辞書の値は次のとおりです。 Sammy, shark, blue、 と ocean.

マップを変数内に保存して印刷してみましょう。

sammy := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
fmt.Println(sammy)
Output
map[animal:shark color:blue location:ocean name:Sammy]

サミーの色を分離したい場合は、 sammy["color"]. それを印刷してみましょう:

fmt.Println(sammy["color"])
Output
blue

マップはデータを保存するためのキーと値のペアを提供するため、Goプログラムの重要な要素になる可能性があります。

結論

この時点で、Goで使用できる主要なデータ型のいくつかをよりよく理解する必要があります。 Go言語でプログラミングプロジェクトを開発する場合、これらの各データ型が重要になります。

Goで利用できるデータ型をしっかりと把握したら、状況に応じてデータ型を変更するためのデータ型の変換方法を学ぶことができます。