前書き

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

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

バックグラウンド

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

通常、数学では、異なるタイプの数値を組み合わせて、何らかの答えを得ることができます。 たとえば、πに5を追加します。

5 + π

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

5 + π = 5 + 3.14 = 8.14

しかし、単語などの別のデータ型で数値を評価しようとすると、物事はあまり意味がなくなります。 次の方程式をどのように解きますか?

shark + 8

コンピューターの場合、各データ型はまったく異なるもので、言葉や数字のようなものです。 そのため、さまざまなデータ型を使用して値を割り当てる方法と、操作を介して値を操作する方法に注意する必要があります。

整数

数学のように、コンピュータープログラミングの_integers_は、正、負、または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)
Output48

出力が示すように、数学演算子「-」は「116」から整数「68」を減算し、「+ 48+」になりました。 変数の宣言の詳細については、*変数のデータ型の宣言*セクションをご覧ください。

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

浮動小数点数

floating-point number_または_float_は、整数として表現できないhttps://en.wikipedia.org/wiki/Real_number[_real numbers]を表すために使用されます。 実数にはすべての有理数と無理数が含まれます。そのため、浮動小数点数には、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)
Output929.24

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

数値型のサイズ

整数と浮動小数点数の区別に加えて、Goにはサイズの静的または動的な性質によって区別される2種類の数値データがあります。 最初のタイプは_architecture-independent_タイプです。つまり、コードが実行されているマシンに関係なく、ビット単位のデータのサイズは変更されません。

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

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

異なるサイズのデータ​​型に加えて、整数のような型には、_signed_と_unsigned_の2つの基本型があります。 `+ int8 `は符号付き整数で、-128〜127の値を持つことができます。 ` 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 `エイリアスの目的は、バイトデータ測定とは関係のない小さな整数ではなく、プログラムが文字列要素の一般的な計算測定としてバイトを使用している場合に明確にすることです。 プログラムがコンパイルされると、「 byte 」と「 uint8 」は同一ですが、多くの場合、「 byte 」は文字データを数値形式で表すために使用されますが、「 uint8 +」はプログラム内の数字を意図しています。

`+ rune `エイリアスは少し異なります。 「 byte 」と「 uint8 」がまったく同じデータである場合、「 rune 」は「 int32 」で決定される範囲のシングルバイトまたは4バイトです。 ` 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では一般に、「+ int64 」または「 uint64 」ではなく、「 int 」または「 uint 」などの実装タイプを使用します。 これにより、通常、ターゲットアーキテクチャの処理速度が最速になります。 たとえば、 ` int64 `を使用して32ビットアーキテクチャにコンパイルする場合、アーキテクチャ全体でデータを移動するには追加のCPUサイクルがかかるため、これらの値の処理には少なくとも2倍の時間がかかります。 代わりに ` int +`を使用した場合、プログラムはそれを32ビットアーキテクチャの32ビットサイズとして定義し、処理が大幅に高速になります。

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

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

オーバーフローと 包み込む

Goは、値がコンパイル時に計算されるか実行時に計算されるかに応じて、格納するように設計されたデータ型よりも大きい値を格納しようとすると、overflow a numberと_wraparound_ a numberの両方の可能性があります。 コンパイル時エラーは、プログラムがプログラムをビルドしようとしたときにエラーを見つけると発生します。 プログラムが実際に実行されている間に、プログラムがコンパイルされた後に実行時エラーが発生します。

次の例では、 `+ maxUint32 +`を最大値に設定します。

package main

import "fmt"

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

次の結果でコンパイルおよび実行されます。

Output4294967295

実行時に値に「1」を追加すると、「+ 0+」にラップアラウンドされます。

Output0

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

package main

import "fmt"

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

}

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

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

Outputprog.go:6:36: constant 4294967296 overflows uint32

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

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

ブール値

ブールデータ型は、「+ true 」または「 false 」の2つの値のいずれかで、データ型として宣言するときに「 bool」として定義されます。 ブールは、コンピューターサイエンスのアルゴリズムに情報を与える数学の論理分岐に関連付けられている真理値を表すために使用されます。

値 `+ true `と ` false `は、Goで事前に宣言された識別子であるため、常に小文字の ` t `と ` f +`になります。

数学の多くの操作は、trueまたはfalseに評価される答えを提供します。

  • より大きい

  • 500> 100真

  • 1> 5 false

  • 未満

  • 200 <400真

  • 4 <2 false

  • 等しい

  • 5 = 5 true

  • 500 = 400偽

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

myBool := 5 > 8

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

fmt.Println(myBool)

「5」は「8」より大きくないため、次の出力を受け取ります。

Outputfalse

Goでより多くのプログラムを作成すると、ブール値がどのように機能するか、および `+ true `または ` false +`のいずれかに評価されるさまざまな関数と操作がプログラムのコースを変更する方法に慣れます。

文字列

文字列は、定数または変数のいずれかになる1つ以上の文字(文字、数字、記号)のシーケンスです。 文字列は、Goの逆引用符 + \ + または二重引用符 + “+`内に存在し、使用する引用符に応じて異なる特性を持ちます。

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

生の文字列リテラル

生の文字列リテラルは、バッククォートの間の文字シーケンスであり、しばしばバックティックと呼ばれます。 引用符内では、逆引用符自体を除き、任意の文字が逆引用符の間に表示されるように表示されます。

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

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

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

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

OutputSay "hello" to Go!\n

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

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

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

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

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

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

ほとんどの場合、解釈された文字列リテラルを使用します。これは、その中にエスケープ文字を許可するためです。 文字列の操作の詳細については、https://www.digitalocean.com/community/tutorials/an-introduction-to-working-with-strings-in-go [Goでの文字列の操作の概要]をご覧ください。

UTF-8文字を含む文字列

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

a := "Hello, 世界"

+ for`ループで + range`キーワードを使用して、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 `は文字列の印字動詞です。 次に、「 for」ループの現在のインデックスである「+ i 」と「 for」ループの現在の文字である「+ c +」の値を指定しました。

最後に、組み込みの「+ len 」関数を使用して、変数「 a +」の全長を出力しました。

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

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

ご覧のとおり、長さは、文字列を範囲指定するのにかかった回数よりも長くなっています。

UTF-8文字列を常に使用するとは限りませんが、使用すると、それらが単一の「+ int32 +」ではなくルーン文字である理由を理解できるようになります。

変数のデータ型を宣言する

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

Goでは、キーワード「+ var +」の後に変数の名前と必要なデータ型が続く変数を定義できます。

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

キーワード `+ var +`が最初に宣言されます:

pi float64

変数の名前 `+ pi +`が後に続きます:

var  float64

そして最後に、データ型 + float64 +

var pi

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

var pi float64 =

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_は、要素の順序付けられたシーケンスです。 アレイの容量は作成時に定義されます。 配列にサイズが割り当てられると、サイズは変更できなくなります。 配列のサイズは静的であるため、メモリを一度しか割り当てないことを意味します。 これにより、配列の処理が多少厳しくなりますが、プログラムのパフォーマンスが向上します。 このため、プログラムを最適化する際に通常配列が使用されます。 次に説明する_Slices_は柔軟性が高く、他の言語の配列と考えるものを構成します。

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

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

[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]

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

スライス数

_slice_は、長さを変更できる要素の順序付きシーケンスです。 スライスは動的にサイズを増やすことができます。 スライスに新しいアイテムを追加するときに、スライスに新しいアイテムを保存するのに十分なメモリがない場合、必要に応じてシステムにさらにメモリを要求します。 スライスは、必要に応じて要素を追加するために拡張できるため、配列よりも一般的に使用されます。

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

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

[]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]

ご覧のとおり、未知のサイズの要素を管理する必要がある場合、スライスは配列よりも汎用性が高くなります。

Maps

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

map[]{}

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

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

中括弧に加えて、マップ全体にコロンもあることに気付くでしょう。 コロンの左側の単語がキーです。 キーは、Goの任意の_comparable_タイプにすることができます。 比較可能な型は、 + strings +、 `+ ints `などのようなプリミティブ型です。 プリミティブ型は言語によって定義され、他の型の組み合わせからは構築されません。 ユーザー定義型にすることもできますが、プログラミングエラーを避けるためにシンプルに保つことをお勧めします。 上記の辞書のキーは、「 name of」、「+ animal」、「+ color」、および「+ location n」です。

コロンの右側の単語は値です。 値は任意のデータ型で構成できます。 上記の辞書の値は、「+ Sammy」、「+ shark」、「+ blue」、および「+ oceans」です。

地図を変数内に保存して印刷します。

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

サミーの色を分離したい場合は、 `+ sammy [” color “] +`を呼び出して分離できます。 それを印刷してみましょう:

fmt.Println(sammy["color"])
Outputblue

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

結論

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

Goで使用可能なデータ型をしっかり把握したら、https://www.digitalocean.com/community/tutorials/how-to-convert-data-types-in-go [データの変換方法]を学習できます。タイプ]状況に応じてデータタイプを変更するため。