Go-quick-guide

提供:Dev Guides
移動先:案内検索

Go-概要

Goは、システムプログラミングを念頭に置いて設計された汎用言語です。 2007年にRobert Griesemer、Rob Pike、Ken ThompsonによってGoogleで最初に開発されました。 強く静的に型付けされ、ガベージコレクションの組み込みサポートを提供し、同時プログラミングをサポートします。

プログラムは、依存関係を効率的に管理するために、パッケージを使用して構築されます。 Goプログラミングの実装では、従来のコンパイルおよびリンクモデルを使用して実行可能バイナリを生成します。 Goプログラミング言語は2009年11月に発表され、Googleの生産システムの一部で使用されています。

Goプログラミングの機能

Goプログラミングの最も重要な機能を以下に示します-

  • 動的言語に類似したパターンを採用する環境のサポート。 たとえば、型推論(x:= 0はint型の変数xの有効な宣言です)
  • コンパイル時間は高速です。
  • 組み込みの同時実行性サポート:軽量プロセス(goルーチン経由)、チャネル、selectステートメント。
  • Goプログラムはシンプルで簡潔で安全です。
  • インターフェイスとタイプの埋め込みのサポート。
  • 外部依存関係のない静的にリンクされたネイティブバイナリの生成。

意図的に除外された機能

言語をシンプルかつ簡潔に保つために、他の同様の言語で一般的に利用可能な以下の機能はGoでは省略されています

  • 型継承のサポート
  • メソッドまたは演算子のオーバーロードのサポート
  • パッケージ間の循環依存関係のサポート
  • ポインター演算のサポート
  • アサーションのサポート
  • 汎用プログラミングのサポート

囲Programsプログラム

Goプログラムの長さは3行から数百万行までさまざまであり、拡張子が「.go」の1つ以上のテキストファイルに書き込む必要があります。 たとえば、hello.go。

「vi」、「vim」、またはその他のテキストエディタを使用して、Goプログラムをファイルに書き込むことができます。

Go-環境設定

ローカル環境のセットアップ

Goプログラミング言語用に環境を設定する場合は、コンピューターで次の2つのソフトウェアを使用できる必要があります-

  • テキストエディター
  • Goコンパイラー

テキストエディタ

プログラムを入力するには、テキストエディターが必要です。 テキストエディタの例には、Windowsメモ帳、OS編集コマンド、ブリーフ、イプシロン、EMACS、およびvimまたはviが含まれます。

テキストエディタの名前とバージョンは、オペレーティングシステムによって異なる場合があります。 たとえば、Windowsではメモ帳が使用され、LinuxまたはUNIXと同様にWindowsではvimまたはviが使用されます。

テキストエディタで作成したファイルは*ソースファイル*と呼ばれます。 プログラムのソースコードが含まれています。 Goプログラムのソースファイルには、通常、拡張子「* .. go」*が付いています。

プログラミングを開始する前に、テキストエディターを用意し、コンピュータープログラムを作成し、ファイルに保存し、コンパイルして、最後に実行する十分な経験があることを確認してください。

Goコンパイラー

ソースファイルに記述されたソースコードは、プログラムの人間が読めるソースです。 CPUが指定された命令に従って実際にプログラムを実行できるように、コンパイルして機械語に変換する必要があります。 Goプログラミング言語コンパイラは、ソースコードを最終的な実行可能プログラムにコンパイルします。

Goディストリビューションは、FreeBSD(リリース8以降)、Linux、Mac OS X(Snow Leopard以降)、および32ビット(386)および64ビット(amd64)x86プロセッサアーキテクチャを備えたWindowsオペレーティングシステムにインストール可能なバイナリとして提供されます。

次のセクションでは、さまざまなOSにGoバイナリ配布をインストールする方法について説明します。

Go Archiveをダウンロード

Goインストール可能アーカイブファイルの最新バージョンをhttps://golang.org/dl/[Go Downloads]からダウンロードします。 このチュートリアルでは、_go1.4.windows-amd64.msi_というバージョンが使用されます。

C:\> goフォルダーにコピーされます。

OS Archive name
Windows go1.4.windows-amd64.msi
Linux go1.4.linux-amd64.tar.gz
Mac go1.4.darwin-amd64-osx10.8.pkg
FreeBSD go1.4.freebsd-amd64.tar.gz

UNIX/Linux/Mac OS XおよびFreeBSDへのインストール

ダウンロードアーカイブを/usr/localフォルダーに抽出し、/usr/local/goにGoツリーを作成します。 たとえば-

tar -C/usr/local -xzf go1.4.linux-amd64.tar.gz

/usr/local/go/binをPATH環境変数に追加します。

OS Output
Linux export PATH = $PATH:/usr/local/go/bin
Mac export PATH = $PATH:/usr/local/go/bin
FreeBSD export PATH = $PATH:/usr/local/go/bin

Windowsへのインストール

MSIファイルを使用し、プロンプトに従ってGoツールをインストールします。 デフォルトでは、インストーラーはc:\ GoのGoディストリビューションを使用します。 インストーラーは、WindowのPATH環境変数にc:\ Go \ binディレクトリーを設定する必要があります。 変更を有効にするために、開いているコマンドプロンプトを再起動します。

インストールの検証

*C:\> Go_WorkSpace* にtest.goという名前のgoファイルを作成します。

ファイル:test.go

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}

今test.goを実行して結果を確認します-

C:\Go_WorkSpace>go run test.go

出力

Hello, World!

Go-プログラム構造

Goプログラミング言語の基本的な構成要素を学習する前に、Goプログラムの最低限の構造について最初に説明し、以降の章で参照できるようにします。

ハローワールドの例

Goプログラムは基本的に次の部分で構成されています-

  • パッケージ宣言
  • パッケージのインポート
  • 関数
  • 変数
  • ステートメントと式
  • コメント

「Hello World」という言葉を出力する簡単なコードを見てみましょう-

package main

import "fmt"

func main() {
  /*This is my first sample program.*/
   fmt.Println("Hello, World!")
}

上記のプログラムのさまざまな部分を見てみましょう-

  • プログラムパッケージmainの最初の行は、このプログラムが含まれるパッケージ名を定義します。 Goプログラムはパッケージで実行されるため、これは必須ステートメントです。 メインパッケージは、プログラムを実行するための開始点です。 各パッケージには、パスと名前が関連付けられています。
  • 次の行のimport "fmt"は、パッケージfmtにあるファイルを含めるようGoコンパイラーに指示するプリプロセッサーコマンドです。
  • 次の行func main()は、プログラムの実行が開始されるメイン関数です。
  • 次の行/…​/はコンパイラーによって無視され、プログラムにコメントを追加するためにあります。 コメントも、JavaまたはC ++のコメントに似た//を使用して表されます。
  • 次の行fmt.Println(…​)は、Goで使用可能な別の関数であり、「Hello、World!」というメッセージが表示されます。画面に表示されます。 ここで、fmtパッケージは、画面にメッセージを表示するために使用されるPrintlnメソッドをエクスポートしました。
  • Printlnメソッドの大文字Pに注意してください。 Go言語では、大文字で始まる名前がエクスポートされます。 エクスポート済みとは、各パッケージのインポーターが関数または変数/定数にアクセスできることを意味します。

Goプログラムの実行

ソースコードをファイルに保存してコンパイルし、最後にプログラムを実行する方法について説明します。 以下の手順に従ってください-

  • テキストエディターを開き、上記のコードを追加します。
  • ファイルを_hello.go_として保存します
  • コマンドプロンプトを開きます。
  • ファイルを保存したディレクトリに移動します。
  • go run _hello.go_と入力し、Enterキーを押してコードを実行します。
  • コードにエラーがない場合、_ "Hello World!" _が画面に表示されます。
$ go run hello.go
Hello, World!

Goコンパイラがパスにあり、ソースファイルhello.goを含むディレクトリで実行されていることを確認してください。

Go-基本的な構文

前の章でGoプログラムの基本構造について説明しました。 これで、Goプログラミング言語の他の基本的な構成要素を簡単に理解できるようになります。

Goのトークン

Goプログラムはさまざまなトークンで構成されています。 トークンは、キーワード、識別子、定数、文字列リテラル、またはシンボルのいずれかです。 たとえば、次のGo文は6つのトークンで構成されています-

fmt.Println("Hello, World!")

個々のトークンは-

fmt
.
Println
(
   "Hello, World!"
)

行区切り記号

Goプログラムでは、行区切りキーはステートメントターミネータです。 つまり、個々のステートメントはCの「;」のような特別な区切り文字を必要としません。 Goコンパイラは、1つの論理エンティティの終わりを示すステートメントターミネータとして「;」を内部に配置します。

たとえば、次のステートメントを見てください-

fmt.Println("Hello, World!")
fmt.Println("I am in Go Programming World!")

コメント

コメントは、Goプログラムのテキストを支援するようなものであり、コンパイラによって無視されます。 それらは/で始まり、以下に示すように文字/で終了します-

/*my first program in Go*/

コメント内にコメントを含めることはできません。また、コメントは文字列または文字リテラル内では発生しません。

識別子

Go識別子は、変数、関数、またはその他のユーザー定義項目を識別するために使用される名前です。 識別子は、文字A〜Zまたはa〜zまたはアンダースコア_で始まり、その後に0個以上の文字、アンダースコア、および数字(0〜9)が続きます。

識別子=文字\ {文字| unicode_digit}。

Goでは、識別子内で@、$、%などの句読点文字を使用できません。 Goは、*大文字と小文字を区別する*プログラミング言語です。 したがって、_Manpower_と_manpower_はGoの2つの異なる識別子です。 ここに受け入れ可能な識別子のいくつかの例があります-

mahesh      kumar   abc   move_name   a_123
myname50   _temp    j      a23b9      retVal

キーワード

次のリストは、Goの予約語を示しています。 これらの予約語は、定数、変数、またはその他の識別子名として使用できません。

break default func interface select
case defer Go map Struct
chan else Goto package Switch
const fallthrough if range Type
continue for import return Var

Goの空白

空白は、空白、タブ、改行文字、コメントを記述するためにGoで使用される用語です。 コメントが含まれている可能性がある空白のみを含む行は、空白行と呼ばれ、Goコンパイラはそれを完全に無視します。

空白は文の一部を別の部分から分離し、コンパイラがintなどの文の1つの要素がどこで終わり、次の要素が始まるかを特定できるようにします。 したがって、次のステートメントで-

var age int;

コンパイラーが区別できるようにするには、intとageの間に少なくとも1つの空白文字(通常はスペース)が必要です。 一方、次の文で-

fruit = apples + oranges;  //get the total fruit

果物と=、または=とリンゴの間には空白文字は必要ありませんが、読みやすくするために空白文字を自由に含めることができます。

Go-データ型

Goプログラミング言語では、データ型とは、異なる型の変数または関数を宣言するために使用される広範なシステムを指します。 変数のタイプによって、ストレージ内で占めるスペースの量と、格納されているビットパターンの解釈方法が決まります。

Goのタイプは次のように分類できます-

Sr.No. Types and Description
1

Boolean types

これらはブール型であり、2つの定義済み定数で構成されます:(a)true(b)false

2

Numeric types

再び算術型であり、a)整数型またはb)プログラム全体の浮動小数点値を表します。

3

String types

文字列型は、文字列値のセットを表します。 その値はバイトのシーケンスです。 文字列は、一度作成された不変の型であり、文字列の内容を変更することはできません。 事前宣言された文字列タイプはstringです。

4

Derived types

(a)ポインター型、(b)配列型、(c)構造型、(d)ユニオン型、(e)関数型f)スライス型g)インターフェイス型h)マップ型i)チャネル型

配列型と構造体型は、集合的に*集合型*と呼ばれます。 関数のタイプは、同じパラメーターと結果タイプを持つすべての関数のセットを指定します。 次のセクションで基本的なタイプについて説明しますが、他のタイプについては今後の章で説明します。

整数型

定義済みのアーキテクチャに依存しない整数型は-

Sr.No. Types and Description
1

uint8

符号なし8ビット整数(0〜255)

2

uint16

符号なし16ビット整数(0〜65535)

3

uint32

符号なし32ビット整数(0〜4294967295)

4

uint64

符号なし64ビット整数(0から18446744073709551615)

5

int8

符号付き8ビット整数(-128〜127)

6

int16

符号付き16ビット整数(-32768〜32767)

7

int32

符号付き32ビット整数(-2147483648〜2147483647)

8

int64

符号付き64ビット整数(-9223372036854775808から9223372036854775807)

フローティングタイプ

定義済みのアーキテクチャに依存しないフロート型は-

Sr.No. Types and Description
1

float32

IEEE-754 32ビット浮動小数点数

2

float64

IEEE-754 64ビット浮動小数点数

3

complex64

float32実数部と虚数部を持つ複素数

4

complex128

float64実数部と虚数部を持つ複素数

nビット整数の値はnビットであり、2の補数算術演算を使用して表されます。

その他の数値タイプ

実装固有のサイズを持つ数値型のセットもあります-

Sr.No. Types and Description
1

byte

uint8と同じ

2

rune

int32と同じ

3

uint

32または64ビット

4

int

uintと同じサイズ

5

uintptr

ポインタ値の未解釈ビットを格納する符号なし整数

Go-変数

変数は、プログラムが操作できるストレージ領域に付けられた名前に他なりません。 Goの各変数には特定のタイプがあり、変数のメモリのサイズとレイアウト、そのメモリ内に格納できる値の範囲、および変数に適用できる操作のセットを決定します。

変数の名前は、文字、数字、およびアンダースコア文字で構成できます。 文字またはアンダースコアで始まる必要があります。 Goでは大文字と小文字が区別されるため、大文字と小文字は区別されます。 前の章で説明した基本タイプに基づいて、次の基本変数タイプがあります-

Sr.No Type & Description
1

byte

通常、単一のオクテット(1バイト)。 これはバイト型です。

2

int

マシンの整数の最も自然なサイズ。

3

float32

単精度浮動小数点値。

Goプログラミング言語では、列挙、ポインター、配列、構造、およびユニオンなど、他のさまざまなタイプの変数を定義することもできます。これについては、以降の章で説明します。 この章では、基本的な変数タイプのみに焦点を当てます。

Goの変数定義

変数定義は、変数用に作成するストレージの場所と量をコンパイラーに指示します。 変数の定義は、データ型を指定し、次のようにその型の1つ以上の変数のリストが含まれています-

var variable_list optional_data_type;

ここで、 optional_data_type は、byte、int、float32、complex64、boolean、または任意のユーザー定義オブジェクトなどを含む有効なGoデータ型であり、 variable_list はコンマで区切られた1つ以上の識別子名で構成されます。 いくつかの有効な宣言がここに示されています-

var  i, j, k int;
var  c, ch byte;
var  f, salary float32;
d =  42;

ステートメント*“ var i、j、k;” *は、変数i、j、およびkを宣言および定義します。これは、タイプintのi、j、およびkという名前の変数を作成するようコンパイラーに指示します。

変数は、宣言で初期化(初期値を割り当て)できます。 変数のタイプは、渡された値に基づいてコンパイラーによって自動的に判断されます。 初期化子は、等号とそれに続く定数式で構成されます-

variable_name = value;

例えば、

d = 3, f = 5;   //declaration of d and f. Here d and f are int

初期化子なしの定義の場合:静的ストレージ期間を持つ変数は、nilで暗黙的に初期化されます(すべてのバイトの値は0です)。他のすべての変数の初期値は、そのデータ型のゼロ値です。

Goでの静的型宣言

静的な型変数宣言は、指定された型と名前で使用可能な変数が1つあることをコンパイラに保証するため、コンパイラは変数の完全な詳細を必要とせずにさらにコンパイルを進めることができます。 変数宣言はコンパイル時にのみ意味を持ち、コンパイラはプログラムのリンク時に実際の変数宣言を必要とします。

変数が型で宣言され、メイン関数内で初期化されている次の例を試してください-

package main

import "fmt"

func main() {
   var x float64
   x = 20.0
   fmt.Println(x)
   fmt.Printf("x is of type %T\n", x)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

20
x is of type float64

Goでの動的型宣言/型推論

動的な型変数の宣言では、渡された値に基づいてコンパイラが変数の型を解釈する必要があります。 コンパイラーは、必要な要件として静的に型を持つ変数を必要としません。

変数が型なしで宣言されている次の例を試してください。 型推論の場合、変数 y を:=演算子で初期化したのに対し、 x は=演算子を使用して初期化されます。

package main

import "fmt"

func main() {
   var x float64 = 20.0

   y := 42
   fmt.Println(x)
   fmt.Println(y)
   fmt.Printf("x is of type %T\n", x)
   fmt.Printf("y is of type %T\n", y)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

20
42
x is of type float64
y is of type int

Goの混合変数宣言

型推論を使用して、さまざまな型の変数を一度に宣言できます。

package main

import "fmt"

func main() {
   var a, b, c = 3, 4, "foo"

   fmt.Println(a)
   fmt.Println(b)
   fmt.Println(c)
   fmt.Printf("a is of type %T\n", a)
   fmt.Printf("b is of type %T\n", b)
   fmt.Printf("c is of type %T\n", c)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

3
4
foo
a is of type int
b is of type int
c is of type string

Goの左辺値と右辺値

Goには2種類の式があります-

  • lvalue -メモリ位置を参照する式は「lvalue」式と呼ばれます。 左辺値は、割り当ての左辺または右辺として表示される場合があります。
  • rvalue -rvalueという用語は、メモリ内のあるアドレスに格納されているデータ値を指します。 右辺値は、値を割り当てることができない式です。つまり、右辺に割り当てることができますが、割り当ての左側ではありません。

変数は左辺値であるため、割り当ての左側に表示される場合があります。 数値リテラルは右辺値であるため、割り当てられない可能性があり、左側に表示できません。

次の文は有効です-

x = 20.0

次の文は無効です。 それはコンパイル時エラーを生成します-

10 = 20

Go-定数

定数は、プログラムの実行中に変更されない可能性がある固定値を指します。 これらの固定値は*リテラル*とも呼ばれます。

定数は、_整数定数、浮動定数、文字定数、または文字列リテラル_などの基本データ型のいずれかです。 列挙定数もあります。

定数は、定義後に値を変更できないことを除いて、通常の変数と同様に扱われます。

整数リテラル

整数リテラルは、10進、8進、または16進定数です。 プレフィックスは、基数または基数を指定します。16進数の場合は0xまたは0X、8進数の場合は0、10進数の場合は何もありません。

整数リテラルには、UとLを組み合わせたサフィックスを付けることもできます。それぞれ、符号なしとロングを表します。 接尾辞は大文字でも小文字でも、任意の順序で指定できます。

ここに整数リテラルのいくつかの例があります-

212        /*Legal*/
215u       /*Legal*/
0xFeeL     /*Legal*/
078        /*Illegal: 8 is not an octal digit*/
032UU      /*Illegal: cannot repeat a suffix*/

以下は、整数リテラルのさまざまなタイプの他の例です-

85        /*decimal*/
0213      /*octal*/
0x4b      /*hexadecimal*/
30        /*int*/
30u       /*unsigned int*/
30l       /*long*/
30ul      /*unsigned long*/

浮動小数点リテラル

浮動小数点リテラルには、整数部、小数点、小数部、指数部があります。 浮動小数点リテラルは、10進数形式または指数形式で表現できます。

小数点形式を使用して表す場合は、小数点、指数、またはその両方を含める必要があり、指数形式を使用して表す場合は、整数部、小数部、またはその両方を含める必要があります。 符号付き指数は、eまたはEによって導入されます。

浮動小数点リテラルの例をいくつか示します-

3.14159      /*Legal*/
314159E-5L   /*Legal*/
510E         /*Illegal: incomplete exponent*/
210f         /*Illegal: no decimal or exponent*/
.e55         /*Illegal: missing integer or fraction*/

エスケープシーケンス

特定の文字の前にバックスラッシュが付いている場合、それらはGoで特別な意味を持ちます。 これらはエスケープシーケンスコードと呼ばれ、改行(\ n)、タブ(\ t)、バックスペースなどを表すために使用されます。 ここでは、そのようなエスケープシーケンスコードのいくつかのリストを持っています-

Escape sequence Meaning
\\ \ character
\' ' character
\" " character
\? ? character
\a Alert or bell
\b Backspace
\f Form feed
\n Newline
\r Carriage return
\t Horizontal tab
\v Vertical tab
\ooo Octal number of one to three digits
\xhh . . . Hexadecimal number of one or more digits

次の例は、プログラムで \ t を使用する方法を示しています-

package main

import "fmt"

func main() {
   fmt.Printf("Hello\tWorld!")
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Hello World!

Goの文字列リテラル

文字列リテラルまたは定数は、二重引用符 ""で囲まれています。 文字列には、文字リテラルに類似した文字が含まれます:プレーン文字、エスケープシーケンス、およびユニバーサル文字。

文字列リテラルを使用して長い行を複数の行に分割し、それらを空白で区切ります。

文字列リテラルの例を次に示します。 3つの形式はすべて同じ文字列です。

"hello, dear"

"hello, \

dear"

"hello, " "d" "ear"

_const_キーワード

次のように、 const プレフィックスを使用して、特定のタイプの定数を宣言できます-

const variable type = value;

次の例は、 const キーワードの使用方法を示しています-

package main

import "fmt"

func main() {
   const LENGTH int = 10
   const WIDTH int = 5
   var area int

   area = LENGTH * WIDTH
   fmt.Printf("value of area : %d", area)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

value of area : 50

CAPITALSで定数を定義することは、優れたプログラミング手法であることに注意してください。

Go-オペレーター

演算子は、特定の数学的または論理的な操作を実行するようコンパイラーに指示する記号です。 Go言語は組み込みの演算子が豊富であり、次の種類の演算子を提供します-

  • 算術演算子
  • 関係演算子
  • 論理演算子
  • ビット演算子
  • 割り当て演算子
  • その他の演算子

このチュートリアルでは、算術、リレーショナル、論理、ビット単位、割り当て、およびその他の演算子を1つずつ説明します。

算術演算子

次の表に、Go言語でサポートされているすべての算術演算子を示します。 変数 A が10を保持し、変数 B が20を保持すると仮定します-

リンク:/go/go_arithmetic_operators [例を表示]

Operator Description Example
+ Adds two operands A + B gives 30
- Subtracts second operand from the first A - B gives -10
* Multiplies both operands A* B gives 200
/ Divides the numerator by the denominator. B/A gives 2
% Modulus operator; gives the remainder after an integer division. B % A gives 0
++ Increment operator. It increases the integer value by one. A++ gives 11
 —  Decrement operator. It decreases the integer value by one. A-- gives 9

関係演算子

次の表に、Go言語でサポートされているすべての関係演算子を示します。 変数 A が10を保持し、変数 B が20を保持すると仮定します-

リンク:/go/go_relational_operators [例を表示]

Operator Description Example
== It checks if the values of two operands are equal or not; if yes, the condition becomes true. (A == B) is not true.
!= It checks if the values of two operands are equal or not; if the values are not equal, then the condition becomes true. (A != B) is true.
> It checks if the value of left operand is greater than the value of right operand; if yes, the condition becomes true. (A > B) is not true.
< It checks if the value of left operand is less than the value of the right operand; if yes, the condition becomes true. (A < B) is true.
>= It checks if the value of the left operand is greater than or equal to the value of the right operand; if yes, the condition becomes true. (A >= B) is not true.
It checks if the value of left operand is less than or equal to the value of right operand; if yes, the condition becomes true. (A ⇐ B) is true.

論理演算子

次の表に、Go言語でサポートされているすべての論理演算子を示します。 変数 A が1を保持し、変数 B が0を保持すると仮定します-

リンク:/go/go_logical_operators [例を表示]

Operator Description Example
&& Called Logical AND operator. If both the operands are non-zero, then condition becomes true. (A && B) is false.
Called Logical OR Operator. If any of the two operands is non-zero, then condition becomes true. (A
B) is true. ! Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false.

次の表は、Go言語でサポートされているすべての論理演算子を示しています。 変数 A が真を保持し、変数 B が偽を保持すると仮定します-

Operator Description Example
&& Called Logical AND operator. If both the operands are false, then the condition becomes false. (A && B) is false.
Called Logical OR Operator. If any of the two operands is true, then the condition becomes true. (A
B) is true. ! Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true, then Logical NOT operator will make it false.

ビット演算子

ビットごとの演算子はビットに対して機能し、ビットごとの操作を実行します。 &、|、および^の真理値表は次のとおりです-

p q p & q p q
p ^ q 0 0 0 0
0 0 1 0 1
1 1 1 1 1
0 1 0 0 1

A = 60と仮定します。およびB = 13。 バイナリ形式では、次のようになります-

A = 0011 1100

B = 0000 1101

A&B = 0000 1100

A | B = 0011 1101

A ^ B = 0011 0001

〜A = 1100 0011

C言語でサポートされているビット演算子は、次の表にリストされています。 変数Aが60を保持し、変数Bが13を保持すると仮定します-

リンク:/go/go_bitwise_operators [例を表示]

[cols=",,",options="header",]
|===
|Operator |Description |Example |& |Binary AND Operator copies a bit to the result if it exists in both operands. |(A & B) will give 12, which is 0000 1100 || |Binary OR Operator copies a bit if it exists in either operand. |(A | B) will give 61, which is 0011 1101 |^ |Binary XOR Operator copies the bit if it is set in one operand but not both. |(A ^ B) will give 49, which is 0011 0001 |<< |Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. |A << 2 will give 240 which is 1111 0000 |>> |Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. |A >> 2 will give 15 which is 0000 1111
|===

=== 割り当て演算子

次の表は、Go言語でサポートされているすべての割り当て演算子を示しています-

リンク:/go/go_assignment_operators [例を表示]

[cols=",,",options="header",]
|===
|Operator |Description |Example |= |Simple assignment operator, Assigns values from right side operands to left side operand |C = A + B will assign value of A + B into C |+= |Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand |C += A is equivalent to C = C + A |-= |Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand |C -= A is equivalent to C = C - A |*= |Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand |C *= A is equivalent to C = C * A |/= |Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand |C/= A is equivalent to C = C/A |%= |Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand |C %= A is equivalent to C = C % A |<<= |Left shift AND assignment operator |C <<= 2 is same as C = C << 2 |>>= |Right shift AND assignment operator |C >>= 2 is same as C = C >> 2 |&= |Bitwise AND assignment operator |C &= 2 is same as C = C & 2 |^= |bitwise exclusive OR and assignment operator |C ^= 2 is same as C = C ^ 2 ||= |bitwise inclusive OR and assignment operator |C |= 2 is same as C = C | 2
|===

=== その他の演算子

 *sizeof* や*?:。*など、Go言語でサポートされている他の重要な演算子がいくつかあります

リンク:/go/go_misc_operator [例を表示]

[cols=",,",options="header",]
|===
|Operator |Description |Example |& |Returns the address of a variable. |&a; provides actual address of the variable. |* |Pointer to a variable. |*a; provides pointer to a variable.
|===

=== Goでの演算子の優先順位

演算子の優先順位は、式内の用語のグループ化を決定します。 これは、式の評価方法に影響します。 特定の演算子は、他の演算子よりも優先順位が高くなっています。たとえば、乗算演算子は加算演算子よりも優先順位が高くなります。

たとえば、x = 7 + 3 * 2;ここでは、演算子*の優先順位が+よりも高いため、xには20ではなく13が割り当てられます。したがって、最初に3 * 2で乗算され、7に加算されます。

ここでは、優先順位が最も高い演算子が表の上部に表示され、優先順位が最も低い演算子が下部に表示されます。 式内では、優先順位の高い演算子が最初に評価されます。

リンク:/go/go_operators_precedence [例を表示]

[cols=",,",options="header",]
|===
|Category |Operator |Associativity |Postfix |() [] -> . ++ - - |Left to right |Unary |+ - ! ~ ++ - - (type)* & sizeof |Right to left |Multiplicative | */% |Left to right |Additive |+ - |Left to right |Shift |<< >> |Left to right |Relational |< <= > >= |Left to right |Equality |== != |Left to right |Bitwise AND |& |Left to right |Bitwise XOR |^ |Left to right |Bitwise OR || |Left to right |Logical AND |&& |Left to right |Logical OR ||| |Left to right |Conditional |?: |Right to left |Assignment |= += -=* =/= %=>>= <<= &= ^= |= |Right to left |Comma |, |Left to right
|===

Go-意思決定

意思決定構造では、プログラマーが、プログラムによって評価またはテストされる1つ以上の条件を、条件が真であると判断された場合に実行されるステートメント、およびオプションで条件が実行された場合に実行される他のステートメントとともに指定する必要があります偽と判断されます。

以下は、ほとんどのプログラミング言語で見られる典型的な意思決定構造の一般的な形式です-

Goでの意思決定ステートメント

Goプログラミング言語は、次のタイプの意思決定ステートメントを提供します。 詳細を確認するには、次のリンクをクリックしてください。

Sr.No Statement & Description
1

if statement

  • ifステートメント*は、ブール式とそれに続く1つ以上のステートメントで構成されます。
2

if…​else statement

  • ifステートメント*の後にオプションの* elseステートメント*を続けることができます。これはブール式がfalseの場合に実行されます。
3

nested if statements

1つの if または else if ステートメントを別の if または else if ステートメント内で使用できます。

4

switch statement

  • switch* ステートメントを使用すると、変数を値のリストと等しいかどうかをテストできます。
5

select statement

  • select* ステートメントは *switch* ステートメントに似ていますが、caseステートメントがチャネル通信を指す点が異なります。

移動-ループ

コードのブロックを数回実行する必要がある場合があります。 一般に、ステートメントは順番に実行されます。関数の最初のステートメントが最初に実行され、次に2番目のステートメントが実行されます。

プログラミング言語は、より複雑な実行パスを可能にするさまざまな制御構造を提供します。

ループステートメントを使用すると、ステートメントまたはステートメントのグループを複数回実行できます。ほとんどのプログラミング言語では、ループステートメントの一般的な形式は次のとおりです-

ループアーキテクチャ

Goプログラミング言語は、ループ要件を処理するために次のタイプのループを提供します。

Sr.No Loop Type & Description
1

for loop

一連のステートメントを複数回実行し、ループ変数を管理するコードを省略します。

2

nested loops

これらは、forループ内の1つまたは複数のループです。

ループ制御ステートメント

ループ制御ステートメントは、実行を通常のシーケンスから変更します。 実行がスコープを離れると、そのスコープで作成されたすべての自動オブジェクトが破棄されます。

Goは次の制御ステートメントをサポートしています-

Sr.No Control Statement & Description
1

break statement

  • for loop* または *switch* ステートメントを終了し、forループまたはswitchの直後のステートメントに実行を転送します。
2

continue statement

これにより、ループは本体の残りをスキップし、反復する前にその状態をすぐに再テストします。

3

goto statement

ラベル付きステートメントに制御を移します。

無限ループ

条件が決して偽にならない場合、ループは無限ループになります。 forループは、この目的で伝統的に使用されています。 forループを形成する3つの式はいずれも必要ないため、条件式を空のままにするかtrueを渡すことで、無限ループを作成できます。

package main

import "fmt"

func main() {
   for true  {
       fmt.Printf("This loop will run forever.\n");
   }
}

条件式が存在しない場合、trueと見なされます。 初期化および増分式を使用できますが、Cプログラマーはより一般的にfor(;;)コンストラクトを使用して無限ループを示します。

注意-Ctrl + Cキーを押すと、無限ループを終了できます。

Go-機能

関数は、一緒にタスクを実行するステートメントのグループです。 すべてのGoプログラムには、少なくとも1つの関数* main()*があります。 コードを個別の機能に分割できます。 コードを異なる関数に分割する方法はユーザー次第ですが、論理的には、各関数が特定のタスクを実行するように分割する必要があります。

関数*宣言*は、関数名、戻り値の型、およびパラメーターについてコンパイラーに通知します。 関数 definition は、関数の実際の本体を提供します。

Go標準ライブラリは、プログラムが呼び出すことができる多数の組み込み関数を提供します。 たとえば、関数* len()*はさまざまな型の引数を取り、型の長さを返します。 文字列が渡された場合、関数は文字列の長さをバイト単位で返します。 配列が渡された場合、関数は配列の長さを返します。

関数は、 method、subroutine 、または procedure とも呼ばれます。

関数を定義する

Goプログラミング言語の関数定義の一般的な形式は次のとおりです-

func function_name( [parameter list] ) [return_types]
{
   body of the function
}

Goプログラミング言語の関数定義は、_function header_と_function body_で構成されています。 ここに関数のすべての部分があります-

  • Func -関数の宣言を開始します。
  • 関数名-関数の実際の名前です。 関数名とパラメーターリストは一緒に関数シグネチャを構成します。
  • パラメータ-パラメータはプレースホルダのようなものです。 関数が呼び出されると、パラメーターに値を渡します。 この値は、実パラメーターまたは引数と呼ばれます。 パラメーターリストは、関数のパラメーターのタイプ、順序、および数を参照します。 パラメーターはオプションです。つまり、関数にパラメーターを含めることはできません。
  • 戻り値の型-関数は値のリストを返す場合があります。 return_typesは、関数が返す値のデータ型のリストです。 一部の関数は、値を返さずに目的の操作を実行します。 この場合、return_typeは不要です。
  • 関数本体-関数の動作を定義するステートメントのコレクションが含まれています。

次のソースコードは、* max()*という関数を示しています。 この関数は2つのパラメータnum1とnum2を取り、2つの間の最大値を返します-

/*function returning the max between two numbers*/
func max(num1, num2 int) int {
  /*local variable declaration*/
   result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result
}

関数を呼び出す

Go関数を作成するときに、関数の機能の定義を指定します。 関数を使用するには、その関数を呼び出して定義済みのタスクを実行する必要があります。

プログラムが関数を呼び出すと、プログラム制御は呼び出された関数に転送されます。 呼び出された関数は定義されたタスクを実行し、returnステートメントが実行されるか、関数終了の閉じ中括弧に到達すると、プログラム制御をメインプログラムに戻します。

関数を呼び出すには、必要なパラメーターとその関数名を渡すだけです。 関数が値を返す場合、戻り値を保存できます。 たとえば-

package main

import "fmt"

func main() {
  /*local variable definition*/
   var a int = 100
   var b int = 200
   var ret int

  /*calling a function to get max value*/
   ret = max(a, b)

   fmt.Printf( "Max value is : %d\n", ret )
}

/*function returning the max between two numbers*/
func max(num1, num2 int) int {
  /*local variable declaration*/
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result
}

main()関数とともにmax()関数を保持し、ソースコードをコンパイルしました。 最終的な実行可能ファイルを実行している間、それは次の結果を生成します-

Max value is : 200

Functionから複数の値を返す

Go関数は複数の値を返すことができます。 たとえば-

package main

import "fmt"

func swap(x, y string) (string, string) {
   return y, x
}
func main() {
   a, b := swap("Mahesh", "Kumar")
   fmt.Println(a, b)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Kumar Mahesh

関数の引数

関数が引数を使用する場合、引数の値を受け入れる変数を宣言する必要があります。 これらの変数は、関数の*仮パラメータ*と呼ばれます。

仮パラメータは、関数内の他のローカル変数のように動作し、関数に入ると作成され、終了すると破棄されます。

関数を呼び出している間、引数を関数に渡すことができる2つの方法があります-

Sr.No Call Type & Description
1

Call by value

このメソッドは、引数の実際の値を関数の仮パラメーターにコピーします。 この場合、関数内のパラメーターを変更しても、引数には影響しません。

2

Call by reference

このメソッドは、引数のアドレスを仮パラメーターにコピーします。 関数内では、呼び出しで使用される実際の引数にアクセスするためにアドレスが使用されます。 これは、パラメーターに加えられた変更が引数に影響することを意味します。

デフォルトでは、Goは値渡しを使用して引数を渡します。 一般に、関数内のコードは、関数の呼び出しに使用される引数を変更できないことを意味します。 上記のプログラムは、max()関数を呼び出している間、同じメソッドを使用しました。

関数の使用法

関数は次の方法で使用できます。

Sr.No Function Usage & Description
1

Function as Value

関数はその場で作成でき、値として使用できます。

2

Function Closures

関数クロージャーは匿名関数であり、動的プログラミングで使用できます。

3

Method

メソッドは、レシーバーを備えた特別な機能です。

Go-スコープルール

プログラミングのスコープとは、定義された変数が存在し、それを超えると変数にアクセスできないプログラムの領域です。 Goプログラミング言語で変数を宣言できる場所は3つあります-

  • 関数またはブロック内(*ローカル*変数)

  • すべての関数の外側(*グローバル*変数)

  • 関数パラメーターの定義( formal パラメーター)

    *local* および *global* 変数と *formal* パラメーターとは何かを調べてみましょう。

ローカル変数

関数またはブロック内で宣言される変数は、ローカル変数と呼ばれます。 それらは、その関数またはコードブロック内にあるステートメントでのみ使用できます。 ローカル変数は、自身の外部の関数には認識されません。 次の例では、ローカル変数を使用しています。 ここで、変数a、b、およびcはすべてmain()関数に対してローカルです。

package main

import "fmt"

func main() {
  /*local variable declaration*/
   var a, b, c int

  /*actual initialization*/
   a = 10
   b = 20
   c = a + b

   fmt.Printf ("value of a = %d, b = %d and c = %d\n", a, b, c)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

value of a = 10, b = 20 and c = 30

グローバル変数

グローバル変数は、関数の外側、通常はプログラムの上部で定義されます。 グローバル変数は、プログラムの存続期間を通じてその値を保持し、プログラムに定義された関数のいずれかからアクセスできます。

グローバル変数には、どの関数からもアクセスできます。 つまり、グローバル変数は、宣言後にプログラム全体で使用できます。 次の例では、グローバル変数とローカル変数の両方を使用します-

package main

import "fmt"

/*global variable declaration*/
var g int

func main() {
  /*local variable declaration*/
   var a, b int

  /*actual initialization*/
   a = 10
   b = 20
   g = a + b

   fmt.Printf("value of a = %d, b = %d and g = %d\n", a, b, g)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

value of a = 10, b = 20 and g = 30

プログラムはローカル変数とグローバル変数に同じ名前を付けることができますが、関数内のローカル変数の値が優先されます。 たとえば-

package main

import "fmt"

/*global variable declaration*/
var g int = 20

func main() {
  /*local variable declaration*/
   var g int = 10

   fmt.Printf ("value of g = %d\n",  g)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

value of g = 10

正式なパラメーター

仮パラメータは、その関数内のローカル変数として扱われ、グローバル変数よりも優先されます。 たとえば-

package main

import "fmt"

/*global variable declaration*/
var a int = 20;

func main() {
  /*local variable declaration in main function*/
   var a int = 10
   var b int = 20
   var c int = 0

   fmt.Printf("value of a in main() = %d\n",  a);
   c = sum( a, b);
   fmt.Printf("value of c in main() = %d\n",  c);
}
/*function to add two integers*/
func sum(a, b int) int {
   fmt.Printf("value of a in sum() = %d\n",  a);
   fmt.Printf("value of b in sum() = %d\n",  b);

   return a + b;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

value of a in main() = 10
value of a in sum() = 10
value of b in sum() = 20
value of c in main() = 30

ローカル変数とグローバル変数の初期化

ローカル変数とグローバル変数は、デフォルト値の0に初期化されます。一方、ポインターはnilに初期化されます。

Data Type Initial Default Value
int 0
float32 0
pointer nil

Go-文字列

Goプログラミングで広く使用されている文字列は、読み取り専用のバイトスライスです。 Goプログラミング言語では、文字列は*スライス*です。 Goプラットフォームには、文字列を操作するためのさまざまなライブラリが用意されています。

  • ユニコード
  • 正規表現
  • ひも

文字列を作成する

文字列を作成する最も直接的な方法は、書くことです-

var greeting = "Hello world!"

コード内で文字列リテラルが検出されるたびに、コンパイラはこの場合の値「Hello world!」を使用して文字列オブジェクトを作成します。

文字列リテラルは、ルーンと呼ばれる有効なUTF-8シーケンスを保持します。 文字列は任意のバイトを保持します。

package main

import "fmt"

func main() {
   var greeting =  "Hello world!"

   fmt.Printf("normal string: ")
   fmt.Printf("%s", greeting)
   fmt.Printf("\n")
   fmt.Printf("hex bytes: ")

   for i := 0; i < len(greeting); i++ {
       fmt.Printf("%x ", greeting[i])
   }

   fmt.Printf("\n")
   const sampleText = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98"

  /*q flag escapes unprintable characters, with + flag it escapses non-ascii
   characters as well to make output unambigous */
   fmt.Printf("quoted string: ")
   fmt.Printf("%+q", sampleText)
   fmt.Printf("\n")
}

これは、次の結果を生成します-

normal string: Hello world!
hex bytes: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21
quoted string: "\xbd\xb2=\xbc \u2318"

-文字列リテラルは不変であるため、一度作成された文字列リテラルは変更できません。

ストリングの長さ

len(str)メソッドは、文字列リテラルに含まれるバイト数を返します。

package main

import "fmt"

func main() {
   var greeting =  "Hello world!"

   fmt.Printf("String Length is: ")
   fmt.Println(len(greeting))
}

これは、次の結果を生成します-

String Length is : 12

文字列の連結

文字列パッケージには、複数の文字列を連結するための join メソッドが含まれています-

strings.Join(sample, " ")

結合は、配列の要素を連結して単一の文字列を作成します。 2番目のパラメーターは、配列の要素の間に配置されるseperatorです。

私たちは次の例を見てみましょう-

package main

import ("fmt" "math" )"fmt" "strings")

func main() {
   greetings :=  []string{"Hello","world!"}
   fmt.Println(strings.Join(greetings, " "))
}

これは、次の結果を生成します-

Hello world!

Go-配列

Goプログラミング言語は、*配列*と呼ばれるデータ構造を提供します。これは、同じタイプの要素の固定サイズの順次コレクションを格納できます。 配列はデータのコレクションを格納するために使用されますが、配列を同じタイプの変数のコレクションと考える方が便利な場合がよくあります。

number0、number1、…​、number99などの個々の変数を宣言する代わりに、numbersなどの1つの配列変数を宣言し、numbers [0]、numbers [1]、…​、numbers [99]を使用して表現します個々の変数。 配列内の特定の要素は、インデックスによってアクセスされます。

すべての配列は、連続したメモリ位置で構成されています。 最下位アドレスは最初の要素に対応し、最上位アドレスは最後の要素に対応します。

Goの配列

配列の宣言

Goで配列を宣言するために、プログラマは次のように要素の型と配列に必要な要素の数を指定します-

var variable_name [SIZE] variable_type

これは「単一次元配列」と呼ばれます。 arraySize はゼロより大きい整数定数でなければならず、 type は有効なGoデータ型であればどれでもかまいません。 たとえば、float32型の balance という10要素の配列を宣言するには、このステートメントを使用します-

var balance [10] float32

ここで、 balance は最大10個の浮動小数点数を保持できる変数配列です。

配列の初期化

あなたはGoで配列を1つずつ、または次のように単一のステートメントを使用して初期化できます-

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

中括弧\ {}の間の値の数は、角括弧[]の間の配列に対して宣言する要素の数より大きくすることはできません。

配列のサイズを省略すると、初期化を保持するのに十分な大きさの配列が作成されます。 したがって、あなたが書く場合-

var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

前の例で作成したのとまったく同じ配列を作成します。 以下は、配列の単一の要素を割り当てるための例です-

balance[4] = 50.0

上記のステートメントは、配列の要素番号5 ^ th ^に値50.0を割り当てます。 すべての配列は、ベースインデックスとも呼ばれる最初の要素のインデックスとして0を持ち、配列の最後のインデックスは、配列の合計サイズから1を引いたものになります。 以下は、上で説明したのと同じ配列の図的表現です-

配列プレゼンテーション

配列要素へのアクセス

配列名にインデックスを付けることにより、要素にアクセスします。 これは、配列の名前の後に角かっこ内に要素のインデックスを配置することによって行われます。 たとえば-

float32 salary = balance[9]

上記のステートメントは、配列から10番目の要素を取得し、その値を給与変数に割り当てます。 以下は、上記の3つの概念すべてを使用する例です。 配列の宣言、割り当て、アクセス-

package main

import "fmt"

func main() {
   var n [10]int/*n is an array of 10 integers*/
   var i,j int

  /*initialize elements of array n to 0*/
   for i = 0; i < 10; i++ {
      n[i] = i + 100/*set element at location i to i + 100*/
   }

  /*output each array element's value*/
   for j = 0; j < 10; j++ {
      fmt.Printf("Element[%d] = %d\n", j, n[j] )
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

アレイの詳細

Goプログラマーには明らかなはずの配列に関連する重要な概念があります-

Sr.No Concept & Description
1

Multi-dimensional arrays

Goは多次元配列をサポートしています。 多次元配列の最も単純な形式は、2次元配列です。

2

Passing arrays to functions

インデックスなしで配列の名前を指定することで、関数に配列へのポインタを渡すことができます。

移動-ポインター

Goのポインターは簡単で楽しく学ぶことができます。 Goプログラミングタスクの中には、ポインターを使用してより簡単に実行できるものもありますが、参照による呼び出しなどの他のタスクはポインターを使用しないと実行できません。 したがって、完璧なGoプログラマーになるには、ポインターを学ぶ必要があります。

ご存じのように、すべての変数はメモリロケーションであり、すべてのメモリロケーションには、メモリ内のアドレスを示すアンパサンド(&)演算子を使用してアクセスできるアドレスが定義されています。 定義された変数のアドレスを出力する次の例を考えてください-

package main

import "fmt"

func main() {
   var a int = 10
   fmt.Printf("Address of a variable: %x\n", &a  )
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Address of a variable: 10328000

あなたはメモリアドレスとは何か、どのようにアクセスするかを理解しました。 次に、ポインターとは何かを見てみましょう。

ポインターとは

  • ポインタ*は、値が別の変数のアドレス、つまりメモリ位置の直接アドレスである変数です。 他の変数や定数と同様に、ポインターを使用して変数アドレスを保存する前に、ポインターを宣言する必要があります。 ポインタ変数宣言の一般的な形式は-
var var_name *var-type

ここで、 type はポインターの基本型です。有効なCデータ型である必要があり、 var-name はポインター変数の名前です。 ポインターの宣言に使用したアスタリスク*は、乗算に使用したものと同じアスタリスクです。 ただし、このステートメントでは、変数をポインターとして指定するためにアスタリスクが使用されています。 有効なポインター宣言は次のとおりです-

var ip *int       /*pointer to an integer*/
var fp *float32   /*pointer to a float*/

すべてのポインタの値の実際のデータ型は、整数、浮動小数点、その他のいずれであっても同じで、メモリアドレスを表す長い16進数です。 異なるデータ型のポインターの唯一の違いは、ポインターが指す変数または定数のデータ型です。

ポインターの使用方法

ポインターを使用して頻繁に実行するいくつかの重要な操作があります。(a)ポインター変数を定義し、(b)ポインターに変数のアドレスを割り当て、(c)ポインター変数に格納されたアドレスの値にアクセスします。

これらの操作はすべて、オペランドで指定されたアドレスにある変数の値を返す単項演算子*を使用して実行されます。 次の例は、これらの操作を実行する方法を示しています-

package main

import "fmt"

func main() {
   var a int = 20  /*actual variable declaration*/
   var ip *int     /*pointer variable declaration*/

   ip = &a /* store address of a in pointer variable*/

   fmt.Printf("Address of a variable: %x\n", &a  )

  /*address stored in pointer variable*/
   fmt.Printf("Address stored in ip variable: %x\n", ip )

  /*access the value using the pointer*/
   fmt.Printf("Value of *ip variable: %d\n", *ip )
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Address of var variable: 10328000
Address stored in ip variable: 10328000
Value of *ip variable: 20

GoのNilポインター

Goコンパイラは、正確なアドレスが割り当てられていない場合に、ポインタ変数にNil値を割り当てます。 これは、変数宣言時に行われます。 nilが割り当てられたポインターは、 nil ポインターと呼ばれます。

nilポインターは、いくつかの標準ライブラリで定義されたゼロの値を持つ定数です。 次のプログラムを検討してください-

package main

import "fmt"

func main() {
   var  ptr *int

   fmt.Printf("The value of ptr is : %x\n", ptr  )
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

The value of ptr is 0

ほとんどのオペレーティングシステムでは、アドレス0のメモリにアクセスすることは許可されていません。これは、メモリがオペレーティングシステムによって予約されているためです。 ただし、メモリアドレス0には特別な意味があります。ポインタがアクセス可能なメモリ位置を指すように意図されていないことを通知します。 ただし、慣例により、ポインターにnil(ゼロ)値が含まれている場合、何も指していないと見なされます。

nilポインタを確認するには、次のようにif文を使用できます-

if(ptr != nil)    /*succeeds if p is not nil*/
if(ptr == nil)   /*succeeds if p is null*/

ポインターの詳細

ポインターには多くの簡単な概念があり、Goプログラミングにとって非常に重要です。 ポインターの次の概念は、Goプログラマーには明確なはずです-

Sr.No Concept & Description
1

Go - Array of pointers

配列を定義して、多数のポインターを保持できます。

2

Go - Pointer to pointer

Goを使用すると、ポインターにポインターを置くことができます。

3

Passing pointers to functions in Go

参照またはアドレスの両方で引数を渡すと、呼び出された関数によって、呼び出された関数で渡された引数を変更できます。

Go-構造

Go配列を使用すると、同じ種類の複数のデータ項目を保持できる変数を定義できます。 Structure は、Goプログラミングで使用できる別のユーザー定義データ型であり、異なる種類のデータ項目を組み合わせることができます。

構造は、レコードを表すために使用されます。 図書館の本を追跡したいとします。 あなたは、各本の次の属性を追跡することができます-

  • タイトル
  • 著者
  • 件名
  • ブックID

このようなシナリオでは、構造は非常に便利です。

構造の定義

構造を定義するには、 type および struct ステートメントを使用する必要があります。 structステートメントは、プログラムに複数のメンバーを持つ新しいデータ型を定義します。 typeステートメントは、この例ではstructであるタイプに名前をバインドします。 構造体ステートメントの形式は次のとおりです-

type struct_variable_type struct {
   member definition;
   member definition;
   ...
   member definition;
}

構造タイプが定義されると、次の構文を使用してそのタイプの変数を宣言するために使用できます。

variable_name := structure_variable_type {value1, value2...valuen}

構造体メンバーへのアクセス

構造体のメンバーにアクセスするには、* member access operator(。)を使用します。memberaccess operatorは、構造変数名とアクセスしたい構造メンバーの間のピリオドとしてコーディングされます。 *struct キーワードを使用して、構造タイプの変数を定義します。 次の例は、構造を使用する方法を説明します-

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books   /*Declare Book1 of type Book*/
   var Book2 Books   /*Declare Book2 of type Book*/

  /*book 1 specification*/
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

  /*book 2 specification*/
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700

  /*print Book1 info*/
   fmt.Printf( "Book 1 title : %s\n", Book1.title)
   fmt.Printf( "Book 1 author : %s\n", Book1.author)
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

  /*print Book2 info*/
   fmt.Printf( "Book 2 title : %s\n", Book2.title)
   fmt.Printf( "Book 2 author : %s\n", Book2.author)
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Book 1 title      : Go Programming
Book 1 author     : Mahesh Kumar
Book 1 subject    : Go Programming Tutorial
Book 1 book_id    : 6495407
Book 2 title      : Telecom Billing
Book 2 author     : Zara Ali
Book 2 subject    : Telecom Billing Tutorial
Book 2 book_id    : 6495700

関数の引数としての構造

他の変数またはポインターを渡すのと非常によく似た方法で、構造体を関数の引数として渡すことができます。 上記の例と同じ方法で構造変数にアクセスします-

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books   /*Declare Book1 of type Book*/
   var Book2 Books   /*Declare Book2 of type Book*/

  /*book 1 specification*/
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

  /*book 2 specification*/
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700

  /*print Book1 info*/
   printBook(Book1)

  /*print Book2 info*/
   printBook(Book2)
}
func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Book title     : Go Programming
Book author    : Mahesh Kumar
Book subject   : Go Programming Tutorial
Book book_id   : 6495407
Book title     : Telecom Billing
Book author    : Zara Ali
Book subject   : Telecom Billing Tutorial
Book book_id   : 6495700

構造体へのポインター

次のように他の変数へのポインタを定義するのと同じ方法で構造体へのポインタを定義できます-

var struct_pointer *Books

これで、上記で定義したポインター変数に構造変数のアドレスを保存できます。 構造変数のアドレスを見つけるには、次のように構造の名前の前に&演算子を配置します-

struct_pointer = &Book1;

その構造へのポインターを使用して構造のメンバーにアクセスするには、「。」を使用する必要があります。次のような演算子-

struct_pointer.title;

構造体ポインタを使用して上記の例を書き直しましょう-

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books  /*Declare Book1 of type Book*/
   var Book2 Books  /*Declare Book2 of type Book*/

  /*book 1 specification*/
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

  /*book 2 specification*/
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700

  /*print Book1 info*/
   printBook(&Book1)

  /*print Book2 info*/
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Book title     : Go Programming
Book author    : Mahesh Kumar
Book subject   : Go Programming Tutorial
Book book_id   : 6495407
Book title     : Telecom Billing
Book author    : Zara Ali
Book subject   : Telecom Billing Tutorial
Book book_id   : 6495700

移動-スライス

Go Sliceは、Go Arrayを抽象化したものです。 Go配列を使用すると、同じ種類の複数のデータ項目を保持できる変数を定義できますが、サイズを動的に増加したり、独自のサブ配列を取得したりする組み込みメソッドは提供されません。 スライスはこの制限を克服します。 Arrayに必要な多くのユーティリティ関数を提供し、Goプログラミングで広く使用されています。

スライスを定義する

スライスを定義するには、サイズを指定せずにスライスを配列として宣言できます。 または、 make 関数を使用してスライスを作成できます。

var numbers []int/*a slice of unspecified size*/
/* numbers == []int{0,0,0,0,0}*/
numbers = make([]int,5,5)/* a slice of length 5 and capacity 5*/

len()およびcap()関数

スライスは配列の抽象化です。 実際には、基礎となる構造として配列を使用します。 * len()関数は、スライスに存在する要素を返します。 cap()*関数は、スライスの容量(つまり、収容できる要素の数)を返します。 次の例では、スライスの使用方法を説明します-

package main

import "fmt"

func main() {
   var numbers = make([]int,3,5)
   printSlice(numbers)
}
func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

len = 3 cap = 5 slice = [0 0 0]

スライスなし

スライスが入力なしで宣言されている場合、デフォルトでは、nilとして初期化されます。 その長さと容量はゼロです。 たとえば-

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

   if(numbers == nil){
      fmt.Printf("slice is nil")
   }
}
func printSlice(x []int){
   fmt.Printf("len = %d cap = %d slice = %v\n", len(x), cap(x),x)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

len = 0 cap = 0 slice = []
slice is nil

サブスライス

スライスでは、* [lower-bound:upper-bound] *を使用してサブスライスを取得するために、下限と上限を指定できます。 たとえば-

package main

import "fmt"

func main() {
  /*create a slice*/
   numbers := []int{0,1,2,3,4,5,6,7,8}
   printSlice(numbers)

  /*print the original slice*/
   fmt.Println("numbers ==", numbers)

  /* print the sub slice starting from index 1(included) to index 4(excluded)*/
   fmt.Println("numbers[1:4] ==", numbers[1:4])

  /* missing lower bound implies 0*/
   fmt.Println("numbers[:3] ==", numbers[:3])

  /* missing upper bound implies len(s)*/
   fmt.Println("numbers[4:] ==", numbers[4:])

   numbers1 := make([]int,0,5)
   printSlice(numbers1)

  /*print the sub slice starting from index 0(included) to index 2(excluded)*/
   number2 := numbers[:2]
   printSlice(number2)

  /*print the sub slice starting from index 2(included) to index 5(excluded)*/
   number3 := numbers[2:5]
   printSlice(number3)

}
func printSlice(x []int){
   fmt.Printf("len = %d cap = %d slice = %v\n", len(x), cap(x),x)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

len = 9 cap = 9 slice = [0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len = 0 cap = 5 slice = []
len = 2 cap = 9  slice = [0 1]
len = 3 cap = 7 slice = [2 3 4]

append()およびcopy()関数

  • append()*関数を使用して、スライスの容量を増やすことができます。 copy()関数を使用すると、ソーススライスの内容が宛先スライスにコピーされます。 たとえば-
package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)

  /*append allows nil slice*/
   numbers = append(numbers, 0)
   printSlice(numbers)

  /* add one element to slice*/
   numbers = append(numbers, 1)
   printSlice(numbers)

  /* add more than one element at a time*/
   numbers = append(numbers, 2,3,4)
   printSlice(numbers)

  /* create a slice numbers1 with double the capacity of earlier slice*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)

  /*copy content of numbers to numbers1*/
   copy(numbers1,numbers)
   printSlice(numbers1)
}
func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

len = 0 cap = 0 slice = []
len = 1 cap = 2 slice = [0]
len = 2 cap = 2 slice = [0 1]
len = 5 cap = 8 slice = [0 1 2 3 4]
len = 5 cap = 16 slice = [0 1 2 3 4]

移動-範囲

*range* キーワードは *for* ループで使用され、配列、スライス、チャネル、またはマップの項目を反復処理します。 配列とスライスの場合、アイテムのインデックスを整数として返します。 マップでは、次のキーと値のペアのキーを返します。 範囲は、1つまたは2つの値を返します。 範囲式の左側で1つの値のみが使用されている場合、それは次の表の最初の値です。
Range expression 1st Value 2nd Value(Optional)
Array or slice a [n]E index i int a[i] E
String s string type index i int rune int
map m map[K]V key k K value m[k] V
channel c chan E element e E none

次の段落は、範囲を使用する方法を示しています-

package main

import "fmt"

func main() {
  /*create a slice*/
   numbers := []int{0,1,2,3,4,5,6,7,8}

  /*print the numbers*/
   for i:= range numbers {
      fmt.Println("Slice item",i,"is",numbers[i])
   }

  /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo"}

  /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }

  /* print map using key-value*/
   for country,capital := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",capital)
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Slice item 0 is 0
Slice item 1 is 1
Slice item 2 is 2
Slice item 3 is 3
Slice item 4 is 4
Slice item 5 is 5
Slice item 6 is 6
Slice item 7 is 7
Slice item 8 is 8
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo

Go-マップ

Goは、一意のキーを値にマップするmapという名前の別の重要なデータ型を提供します。 キーは、後で値を取得するために使用するオブジェクトです。 キーと値を指定すると、その値をMapオブジェクトに保存できます。 値を保存したら、そのキーを使用して値を取得できます。

マップの定義

マップを作成するには、 make 関数を使用する必要があります。

/* declare a variable, by default map will be nil*/
var map_variable map[key_data_type]value_data_type

/* define the map as nil map can not be assigned any value*/
map_variable = make(map[key_data_type]value_data_type)

次の例は、マップを作成して使用する方法を示しています-

package main

import "fmt"

func main() {
   var countryCapitalMap map[string]string
  /* create a map*/
   countryCapitalMap = make(map[string]string)

  /* insert key-value pairs in the map*/
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"

  /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }

  /* test if entry is present in the map or not*/
   capital, ok := countryCapitalMap["United States"]

  /* if ok is true, entry is present otherwise entry is absent*/
   if(ok){
      fmt.Println("Capital of United States is", capital)
   } else {
      fmt.Println("Capital of United States is not present")
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Capital of India is New Delhi
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of United States is not present

delete()関数

delete()関数は、マップからエントリを削除するために使用されます。 マップと、削除する対応するキーが必要です。 たとえば-

package main

import "fmt"

func main() {
  /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}

   fmt.Println("Original map")

  /*print map*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }

  /*delete an entry*/
   delete(countryCapitalMap,"France");
   fmt.Println("Entry for France is deleted")

   fmt.Println("Updated map")

  /*print map*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Original Map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
Updated Map
Capital of India is New Delhi
Capital of Italy is Rome
Capital of Japan is Tokyo

移動-再帰

再帰は、自己相似の方法でアイテムを繰り返すプロセスです。 同じ概念がプログラミング言語にも当てはまります。 プログラムが同じ関数内の関数の呼び出しを許可する場合、その関数は再帰関数呼び出しと呼ばれます。 次の例を見てください-

func recursion() {
   recursion()/*function calls itself*/
}
func main() {
   recursion()
}

Goプログラミング言語は再帰をサポートしています。 つまり、関数が自分自身を呼び出すことができます。 しかし、再帰を使用している間、プログラマは関数から終了条件を定義するように注意する必要があります。定義しないと、無限ループになります。

Goの再帰の例

再帰関数は、数の階乗の計算、フィボナッチ数列の生成など、多くの数学的な問題を解決するのに非常に役立ちます。

例1:Goの再帰を使用した階乗の計算

次の例では、再帰関数を使用して、与えられた数の階乗を計算します-

package main

import "fmt"

func factorial(i int)int {
   if(i <= 1) {
      return 1
   }
   return i * factorial(i - 1)
}
func main() {
   var i int = 15
   fmt.Printf("Factorial of %d is %d", i, factorial(i))
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Factorial of 15 is 2004310016

例2:Goで再帰を使用するフィボナッチ数列

次の例は、再帰関数を使用して、指定された数のフィボナッチ数列を生成する方法を示しています-

package main

import "fmt"

func fibonaci(i int) (ret int) {
   if i == 0 {
      return 0
   }
   if i == 1 {
      return 1
   }
   return fibonaci(i-1) + fibonaci(i-2)
}
func main() {
   var i int
   for i = 0; i < 10; i++ {
      fmt.Printf("%d ", fibonaci(i))
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

0 1 1 2 3 5 8 13 21 34

Go-型キャスト

型キャストは、変数をあるデータ型から別のデータ型に変換する方法です。 たとえば、long値を単純な整数に格納する場合は、cast long to intと入力できます。 *キャスト演算子*を使用して、値をあるタイプから別のタイプに変換できます。 その構文は次のとおりです-

type_name(expression)

次の例を考えてみましょう。キャスト演算子により、ある整数変数を別の整数変数で除算した結果が浮動小数点演算として実行されます。

package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32

   mean = float32(sum)/float32(count)
   fmt.Printf("Value of mean : %f\n",mean)
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Value of mean : 3.400000

Go-インターフェース

Goプログラミングは、メソッドシグネチャのセットを表す interfaces と呼ばれる別のデータ型を提供します。 structデータ型はこれらのインターフェイスを実装して、インターフェイスのメソッドシグネチャのメソッド定義を保持します。

構文

/*define an interface*/
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/*define a struct*/
type struct_name struct {
  /*variables*/
}

/* implement interface methods*/
func (struct_name_variable struct_name) method_name1() [return_type] {
  /*method implementation*/
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
  /*method implementation*/
}

package main

import ("fmt" "math")

/*define an interface*/
type Shape interface {
   area() float64
}

/*define a circle*/
type Circle struct {
   x,y,radius float64
}

/*define a rectangle*/
type Rectangle struct {
   width, height float64
}

/* define a method for circle (implementation of Shape.area())*/
func(circle Circle) area() float64 {
   return math.Pi *circle.radius* circle.radius
}

/* define a method for rectangle (implementation of Shape.area())*/
func(rect Rectangle) area() float64 {
   return rect.width * rect.height
}

/*define a method for shape*/
func getArea(shape Shape) float64 {
   return shape.area()
}

func main() {
   circle := Circle{x:0,y:0,radius:5}
   rectangle := Rectangle {width:10, height:5}

   fmt.Printf("Circle area: %f\n",getArea(circle))
   fmt.Printf("Rectangle area: %f\n",getArea(rectangle))
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Circle area: 78.539816
Rectangle area: 50.000000

Go-エラー処理

Goプログラミングは、次の宣言の組み込みエラーインターフェイスタイプを持つ非常にシンプルなエラー処理フレームワークを提供します-

type error interface {
   Error() string
}

関数は通常、最後の戻り値としてエラーを返します。 次のように基本的なエラーメッセージを作成するには、 errors.New を使用します-

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}

戻り値とエラーメッセージを使用します。

result, err:= Sqrt(-1)

if err != nil {
   fmt.Println(err)
}

package main

import "errors"
import "fmt"
import "math"

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}
func main() {
   result, err:= Sqrt(-1)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }

   result, err = Sqrt(9)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Math: negative number passed to Sqrt
3

Go-questions-answers