変数は、マスターすることが重要なプログラミングの概念です。変数は、プログラムで使用している値の代わりになる記号です。
このチュートリアルでは、変数の基本と、作成するGoプログラム内での変数のベストプラクティスについて説明します。
変数の理解
技術的には、変数は記憶場所を値に割り当て、それをシンボリック名または識別子に関連付けることです。コンピュータプログラム内でその保存された値を参照するために変数名を使用します。
変数は、値に結びつけられた名前のついたラベルと考えることができます。
例えば、整数1032049348
があり、長い数字を繰り返し入力する代わりに変数に保存したいとします。これを実現するために、変数i
のように覚えやすい名前を使用できます。値を変数に保存するには、次の構文を使用します:
この変数は、値に結びつけられたラベルのようなものと考えることができます。
このラベルには変数名i
が書かれており、整数値1032049348
に結びつけられています。
フレーズi := 1032049348
は、いくつかの部分からなる宣言と代入文です:
- 変数名(
i
) - 短い変数宣言代入(
:=
) - 変数名に関連付けられている値(
1032049348
) - Goによって推論されたデータ型(
int
)
次のセクションでは、型を明示的に設定する方法を見ていきます。
これらの部分が合わさって、変数i
を整数1032049348
の値と等しくするステートメントを構成しています。
変数に値を等しく設定するとすぐに、その変数を初期化または作成します。それが済んだら、値の代わりに変数を使用する準備が整います。
一度i
を1032049348
の値に等しく設定したら、整数の代わりにi
を使用できるので、それを出力してみましょう:
Output1032049348
また、変数を使って簡単かつ迅速に数学的な計算を行うこともできます。i := 1032049348
を使って、以下の構文で整数値813
を引くことができます:
Output1032048535
この例では、Goが計算を行い、変数i
から813を引いて合計1032048535
を返します。
数学の話になると、変数は数学的な方程式の結果に等しく設定することができます。2つの数値を足して、その合計の値を変数x
に格納することもできます:
この例は代数に似ていることに気づかれたかもしれません。数式や方程式内で数字や数量を表すために文字や他の記号を使用するのと同じように、変数はデータ型の値を表す記号的な名前です。Goの正しい構文のために、変数がどの方程式の左側にあるかを確認する必要があります。
それでは、x
を出力してみましょう:
Output221
Goが221
という値を返したのは、変数x
が76
と145
の合計に等しく設定されたためです。
変数は整数だけでなく、あらゆるデータ型を表すことができます:
これらの変数のいずれかを出力すると、Goはその変数が等価なものを返します。文字列slice
データ型の代入文を使ってみましょう:
Output[one two three]
スライスの値[]string{"one", "two", "three"}
を変数slice
に代入し、その値をfmt.Println
関数を使ってslice
を呼び出すことで出力しました。
変数は、コンピュータ内のメモリの小さな領域を確保し、その領域に指定された値を受け入れ、そのスペースに関連付けます。
変数の宣言
Goでは、変数を宣言する方法がいくつかあり、場合によっては同じ変数と値を宣言する方法が複数あります。
データ型int
の変数i
を初期化せずに宣言することができます。つまり、値を入れるスペースを宣言しますが、初期値は与えません:
これにより、データ型int
の変数i
が宣言されます。
値を初期化するために、等号(=
)演算子を使用することができます。以下の例のようにです:
Go言語では、これらの宣言形式はどちらも長い変数宣言と呼ばれています。
また、短い変数宣言を使用することもできます:
この場合、変数i
とデータ型int
があります。データ型を指定しない場合、Goはデータ型を推測します。
変数を宣言する三つの方法を用いて、Goコミュニティは以下の慣習を採用しています:
-
変数を初期化しない場合にのみ、長い形式
var i int
を使用します。 -
宣言と初期化を行う場合には、短い形式
i := 1
を使用します。 -
Goにデータ型を推測させたくないが、短い変数宣言を使用したい場合は、希望する型で値をラップすることができます。以下の構文で行います:
値を初期化する際に長い変数宣言形式を使用することは、Goでは慣用的ではありません:
Goコミュニティが通常どのように変数を宣言するかを守ることは、他の人がプログラムをスムーズに読めるようにするための良い習慣です。
ゼロ値
すべての組み込み型にはゼロ値があります。割り当てられた変数は、値が一度も割り当てられていなくても使用できます。以下の型のゼロ値を見ることができます:
Outputvar a int = 0
var b string = ""
var c float64 = 0
var d bool = false
私たちはfmt.Printf
ステートメントで%T
動詞を使用しました。これは、関数に変数のデータ型
を出力するように指示します。
Goでは、すべての値がゼロ
値を持っているため、他のいくつかの言語のように未定義
の値を持つことはできません。例えば、他の言語ではブーリアン
は未定義
、真
、または偽
になることができ、変数に3
つの状態を許容します。Goでは、ブーリアン値に対して2
つ以上の状態を持つことはできません。
変数の命名:ルールとスタイル
変数の命名はかなり柔軟ですが、留意すべきいくつかのルールがあります:
- 変数名は1つの単語である必要があります(スペースがないことを意味します)。
- 変数名は、文字、数字、およびアンダースコア(
_
)のみで構成されている必要があります。 - 変数名を数字で始めることはできません。
これらのルールに従って、有効な変数名と無効な変数名の両方を見てみましょう:
Valid | Invalid | Why Invalid |
---|---|---|
userName |
user-name |
Hyphens are not permitted |
name4 |
4name |
Cannot begin with a number |
user |
$user |
Cannot use symbols |
userName |
user name |
Cannot be more than one word |
さらに、変数の命名時には大文字と小文字が区別されることに注意してください。これらの名前 userName
、USERNAME
、UserName
、および uSERnAME
はすべて完全に異なる変数です。プログラム内で類似した変数名を使用しないことがベストプラクティスです。これにより、現在および将来の共同作業者と自分自身が変数を整理しやすくなります。
変数は大文字と小文字を区別しますが、Go では変数の最初の文字の大文字と小文字には特別な意味があります。変数が大文字で始まる場合、その変数は宣言されたパッケージの外からアクセス可能です(または exported
)。変数が小文字で始まる場合、それは宣言されたパッケージ内でのみ利用可能です。
Email
は大文字で始まり、他のパッケージからアクセスできます。password
は小文字で始まり、宣言されたパッケージ内でのみアクセス可能です。
Go では非常に簡潔な(または短い)変数名を使用するのが一般的です。変数に userName
と user
のどちらを使用するかを選ぶ場合、user
を選ぶのが慣用的です。
スコープも変数名の簡潔さに影響を与えます。ルールは、変数が存在するスコープが小さいほど、変数名も小さくなるというものです。
大きなスコープでnames
変数を使用しているため、プログラム内でその意味を覚えやすくするために、より意味のある名前を付けるのが一般的です。ただし、i
とn
変数は次の行ですぐに使用され、その後再び使用されません…このため、コードを読む人が変数がどこで使用されているのか、またそれらが何を意味するのかについて混乱することはありません。
次に、変数スタイルに関するいくつかの注意点を説明します。スタイルは、複数の単語からなる名前にはアンダースコアではなくMixedCaps
またはmixedCaps
を使用することです。
Conventional Style | Unconventional Style | Why Unconventional |
---|---|---|
userName |
user_name |
Underscores are not conventional |
i |
index |
prefer i over index as it is shorter |
serveHTTP |
serveHttp |
acronyms should be capitalized |
スタイルについて最も重要なことは、一貫性を保ち、チームがそのスタイルに同意することです。
変数の再代入
「変数」という言葉が示すように、Goの変数は容易に変更できます。これは、以前に代入された変数に異なる値を再代入することができることを意味します。再代入が可能であることは、プログラムの過程ですでに初期化された変数にユーザー生成の値を受け入れる必要がある場合や、以前に定義されたものに代入を変更する必要がある場合に便利です。
すでに定義されている変数が不明な場合、他の人が書いた大規模なプログラムを扱う際に、変数を容易に再代入できることを知っておくと役立ちます。
int
型の変数i
に76
の値を代入し、次に42
の新しい値を代入しましょう:
Output76
42
この例は、まず変数i
に整数値を代入し、次に42
の値を代入して変数i
を再代入できることを示しています。
注意:変数を宣言して初期化する際には:=
を使用できますが、すでに宣言された変数の値を単に変更する場合は等号演算子(=
)のみを使用する必要があります。
Goは型付き
言語であるため、ある型を別の型に代入することはできません。例えば、int
型の変数に"Sammy"
の値を代入することはできません:
異なる型を互いに代入しようとすると、コンパイル時エラーが発生します:
Outputcannot use "Sammy" (type string) as type int in assignment
Goでは、変数名を複数回使用することは許可されていません:
Outputs redeclared in this block
同じ変数名に対して短い変数宣言を複数回使用しようとすると、コンパイルエラーも発生します。これは誤って発生する可能性があるため、エラーメッセージの意味を理解することが役立ちます:
Outputno new variables on left side of :=
変数宣言と同様に、変数の命名に配慮することで、将来あなたや他の人がプログラムを再訪した際の可読性が向上します。
複数代入
Goでは、同じ行内で複数の変数に複数の値を割り当てることができます。これらの値はそれぞれ異なるデータ型であっても構いません:
Outputshark
2.05
15
この例では、変数j
に文字列"shark"
が割り当てられ、変数k
に浮動小数点数2.05
が割り当てられ、変数l
に整数15
が割り当てられています。
この方法で1行で複数の変数に複数の値を割り当てることで、コードの行数を減らすことができます。ただし、コードの行数を減らすために可読性を犠牲にしないことが重要です。
グローバル変数とローカル変数
プログラム内で変数を使用する際には、変数のスコープを念頭に置くことが重要です。変数のスコープとは、特定のプログラムのコード内でその変数にアクセスできる特定の場所を指します。つまり、すべての変数が特定のプログラムのすべての部分からアクセスできるわけではなく、一部の変数はグローバルであり、一部はローカルであるということです。
グローバル変数は関数の外側に存在します。ローカル変数は関数の内側に存在します。
グローバル変数とローカル変数の動作を見てみましょう:
Outputlocal
global
ここでは、var g = "global"
を使って関数の外でグローバル変数を作成します。次に、printLocal()
という関数を定義します。関数の内部では、l
というローカル変数が割り当てられ、その後出力されます。プログラムはprintLocal()
を呼び出し、その後グローバル変数g
を出力することで終了します。
なぜなら、g
はグローバル変数であるため、printLocal()
内で参照することができます。前のプログラムをそのように修正してみましょう:
Outputlocal
global
global
まず、グローバル変数g
を宣言します、var g = "global"
。main
関数では、printLocal
関数を呼び出し、その中でローカル変数l
を宣言し、出力します、fmt.Println(l)
。その後、printLocal
はグローバル変数g
を出力します、fmt.Println(g)
。g
はprintLocal
内で定義されていないにもかかわらず、グローバルスコープで宣言されているためアクセスできます。最後に、main
関数もg
を出力します。
次に、関数の外でローカル変数を呼び出してみましょう:
Outputundefined: l
ローカル変数は、それが割り当てられた関数の外では使用できません。そうしようとすると、コンパイル時にundefined
エラーが発生します。
グローバル変数とローカル変数に同じ変数名を使用する別の例を見てみましょう:
Output10
7
5
このプログラムでは、num1
変数を2回宣言しました。まず、グローバルスコープでnum1
を宣言し、var num1 = 5
とし、次にprintNumbers
関数のローカルスコープ内で再びnum1 := 10
と宣言しました。main
プログラムからnum1
を出力すると、値5
が出力されます。これは、main
がグローバル変数の宣言のみを認識するためです。しかし、printNumbers
関数からnum1
を出力すると、ローカル宣言を認識し、値10
を出力します。printNumbers
は新しい変数num1
を作成し、それに10
の値を割り当てますが、これは値5
のグローバルなnum1
インスタンスには影響しません。
変数を扱う際には、プログラムのどの部分が各変数にアクセスする必要があるかも考慮する必要があります。適宜グローバル変数またはローカル変数を採用します。Goプログラム全体を通して、ローカル変数が一般的であることがわかります。
定数
定数は変数に似ていますが、一度宣言されると変更できません。定数は、プログラム内で複数回使用されるが変更されるべきでない値を定義するのに便利です。
例えば、ショッピングカートシステムの税率を宣言したい場合、定数を使用してプログラムの異なる部分で税金を計算することができます。将来的に税率が変更された場合、プログラム内の1箇所の値を変更するだけで済みます。変数を使用した場合、プログラムのどこかで誤って値を変更してしまい、不適切な計算になる可能性があります。
定数を宣言するには、以下の構文を使用できます:
OutputSammy
定数を宣言した後に変更しようとすると、コンパイル時エラーが発生します:
Outputcannot assign to shark
定数はuntyped
にすることができます。これは整数型データなどの数値を扱う際に便利です。定数がuntyped
の場合、明示的に変換されますが、typed
定数はそうではありません。定数の使用方法を見てみましょう:
Output8760
21900
21960
型付きの定数を宣言すると、その型になります。ここで定数leapYear
を宣言する際、データ型int32
として定義します。したがって、これはtyped
定数であり、int32
データ型のみで操作できます。型なしで宣言したyear
定数は、untyped
と見なされます。このため、任意の整数データ型で使用できます。
hours
が定義されたとき、明示的に型を指定しなかったため、型int
と推論されました(hours := 24
)。minutes
を宣言する際、明示的にint32
と宣言しました(minutes := int32(60)
)。
それでは、それぞれの計算がどのように機能するかを見ていきましょう:
この場合、hours
はint
型で、years
は型なしです。プログラムがコンパイルされるとき、years
は明示的にint
型に変換され、乗算操作が成功します。
この場合、minutes
はint32
型で、year
は型なしです。プログラムがコンパイルされるとき、years
は明示的にint32
型に変換され、乗算操作が成功します。
この場合、minutes
はint32
型で、leapYear
は型付きのint32
型の定数です。両方の変数がすでに同じ型であるため、コンパイラはこの時何もする必要がありません。
もし互換性のない型付き
の2つの型を乗算しようとすると、プログラムはコンパイルされません:
Outputinvalid operation: hours * leapYear (mismatched types int and int32)
この場合、hours
はint
型と推論され、leapYear
は明示的にint32
型と宣言されています。Goは型付き言語であるため、int
型とint32
型は数学的な操作に互換性がありません。それらを乗算するためには、一方をint32
型またはint
型に変換する必要があります。
結論
このチュートリアルでは、Go言語における変数の一般的な使用例についていくつか見てきました。変数はプログラミングの重要な構成要素であり、プログラム内で使用するデータ型の値の代わりとなるシンボルとして機能します。
Source:
https://www.digitalocean.com/community/tutorials/how-to-use-variables-and-constants-in-go