Skip to content

基本構文

Go の基本構文はとても分かりやすく、最もシンプルな例から始めましょう。

go
package main

import "fmt"

func main() {
   fmt.Println("Hello 世界!")
}
  • package キーワードは、現在の go ファイルがどのパッケージに属しているかを宣言します。エントリーファイルは必ず main パッケージとして宣言し、エントリー関数は main 関数です。カスタムパッケージや関数を定義する際は、これらとの重複を避けるべきです。

  • import はインポートキーワードで、後にインポートするパッケージ名が続きます。

  • func は関数宣言キーワードで、関数を宣言するために使用します。

  • fmt.Println("Hello 世界!") はステートメントで、fmt パッケージの Println 関数を呼び出して出力を行います。

以上が簡単な構文の紹介です。次に、これらの概念についてより詳しく見ていきましょう。

パッケージ

Go では、プログラムはパッケージをリンクして構築されます。Go でのインポートの最小単位は .go ファイルではなくパッケージです。パッケージは実際にはフォルダであり、英名は package です。パッケージ内ではすべての変数、定数、および定義された型が共有されます。パッケージの命名スタイルはすべて小文字で、できるだけ短くすることが推奨されます。

可視性

前述したように、パッケージ内ではすべての変数、定数、および定義された型が共有されますが、パッケージ外ではそうではありません。場合によっては、特定の型にアクセスさせたくないこともあるため、可視性を制御する必要があります。他の OOP 言語では PublicPrivate などのキーワードを見たことがあるかもしれませんが、Go 言語にはこれらはありません。可視性を制御する方法は非常にシンプルで、ルールは以下の通りです。

  • 名前が大文字で始まる場合、それはパブリックな型/変数/定数です
  • 名前が小文字またはアンダースコアで始まる場合、それはプライベートな型/変数/定数です

例えば、以下の例では、定数 MyName はパブリックで、定数 mySalary はプライベートです。

go
package example

// パブリック
const MyName = "jack"

// プライベート
const mySalary = 20_000

この可視性のルールは Go 言語全体のあらゆる場所に適用されます。

インポート

パッケージ内の型/メソッド/関数/変数を使用するためにパッケージをインポートします。インポートの構文は import にパッケージ名を追加するだけです。

go
package main

import "example"

複数のパッケージをインポートする場合は、次のように書くことができます。

go
package main

import "example"
import "example1"

または括弧で囲むこともできます。以下の方法は実践でより一般的に使用されます。

go
package main

import (
  "example"
  "example1"
)

パッケージ名が重複している場合や、パッケージ名が複雑な場合は、別名を付けることもできます。

go
package main

import (
  e "example"
  e1 "example1"
)

別名がアンダースコア _ の場合、それは匿名インポートです。匿名インポートされたパッケージは使用できません。これは通常、パッケージ内の init 関数を読み込むために行われますが、パッケージ内の型を使用する必要はありません。一般的な例としては、データベースドライバの登録がありますが、ドライバを手動で使用する必要はありません。

go
package main

import (
  e "example"
  _ "mysql-driver-go"
)

インポート後、パッケージ内の型にアクセスしたい場合は、パッケージ名。識別子 でアクセスできます。例えば、以下の例でプライベートな型にアクセスしようとすると、コンパイラはアクセスできないと通知します。

go
package main

import (
  "example"
   "fmt"
)

func main() {
    fmt.Println(example.MyName)
}

特別なインポート方法として、パッケージ内のすべての型を現在のパッケージスコープにインポートする方法があります。この方法でインポートされた型は . 演算子でアクセスする必要はありませんが、同名の型がある場合はコンパイルできません。

go
package main

import (
  . "example"
)

WARNING

Go では循環インポートはできません。直接的にも間接的にもです。例えば、パッケージ A がパッケージ B をインポートし、パッケージ B もパッケージ A をインポートしている場合、これは直接的な循環インポートです。パッケージ A がパッケージ C をインポートし、パッケージ C がパッケージ B をインポートし、パッケージ B がパッケージ A をインポートしている場合、これは間接的な循環インポートです。循環インポートがある場合、コンパイルできません。

内部パッケージ

Go では、internal という名前のパッケージは内部パッケージとして约定されており、外部パッケージは内部パッケージ内のコンテンツにアクセスできません。そうでない場合、コンパイルエラーになります。以下に例を示します。

/home/user/go/
    src/
        crash/
            bang/              (go code in package bang)
                b.go
        foo/                   (go code in package foo)
            f.go
            bar/               (go code in package bar)
                x.go
            internal/
                baz/           (go code in package baz)
                    z.go
            quux/              (go code in package main)
                y.go

ファイル構造から、crash パッケージは baz パッケージ内の型にアクセスできないことがわかります。

コメント

Go は単一行コメントと複数行コメントをサポートしています。コメントとコンテンツの間には 1 つのスペースを空けることを推奨します。

go
// これは main パッケージです
package main

// fmt パッケージをインポートしました
import "fmt"

/*
*
これは起動関数 main 関数です
*/
func main() {
  // これはステートメントです
  fmt.Println("Hello 世界!")
}

識別子

識別子は名前で、パッケージ名、関数名、変数名などに使用されます。命名ルールは以下の通りです。

  • 文字、数字、アンダースコアのみで構成できます
  • 文字とアンダースコアのみで始まります
  • 大文字と小文字は厳密に区別されます
  • 既存の識別子と重複することはできません。つまり、パッケージ内で一意である必要があります
  • Go の組み込みキーワードと衝突することはできません

以下にすべての組み込みキーワードをリストします。詳細は リファレンスマニュアル - 識別子 をご覧ください。

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 言語でサポートされている演算子の優先順位リストです。詳細は リファレンスマニュアル - 演算子 をご覧ください。

Precedence    Operator
    5             *  /  %  <<  >>  &  &^
    4             +  -  |  ^
    3             ==  !=  <  <=  >  >=
    2             &&
    1             ||

少し注意が必要な点は、Go 言語では ~ を否定演算子として使用せず、^ 記号を流用していることです。2 つの数値で ^ を使用する場合、例えば a^b、それは XOR 演算子です。1 つの数値でのみ使用する場合、例えば ^a、それは否定演算子です。Go も強化代入演算子をサポートしています。

go
a += 1
a /= 2
a &^= 2

TIP

Go 言語にはインクリメントおよびデクリメント演算子はありません。これらはステートメント statement にダウングレードされており、オペランドの後にのみ配置できると規定されているため、i++++i のような問題を気にする必要はありません。

a++ // 正しい
++a // 間違い
a-- // 正しい

また、これらは戻り値を持たないため、a = b++ のようなステートメントは正しくありません。

リテラル

リテラルは、コンピュータサイエンスの用語では、ソースコード内の固定値を表す記号で、字面值とも呼ばれます。2 つの呼び方は同じ意味で、何を書いたかがそのまま値になります。

整数リテラル

読みやすくするために、アンダースコア _ を使用して数字を区切ることができます。ただし、接頭辞記号の後数字の間でのみ使用できます。

go
24 // 24
024 // 24
2_4 // 24
0_2_4 // 24
10_000 // 10k
100_000 // 100k
0O24 // 20
0b00 // 0
0x00 // 0
0x0_0 // 0

浮動小数点リテラル

異なる接頭辞を使用して、異なる基数の浮動小数点数を表すことができます。

go
0.
72.40
072.40       // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5.         // == 15.0
0.15e+0_2    // == 15.0

0x1p-2       // == 0.25
0x2.p10      // == 2048.0
0x1.Fp+0     // == 1.9375
0X.8p-0      // == 0.5
0X_1FFFP-16  // == 0.1249847412109375
0x15e-2      // == 0x15e - 2 (整数の減算)

複素数リテラル

go
0i
0123i         // == 123i
0o123i        // == 0o123 * 1i == 83i
0xabci        // == 0xabc * 1i == 2748i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
0x1p-2i       // == 0x1p-2 * 1i == 0.25i

文字リテラル

文字リテラルは単一引用符 '' で囲む必要があります。Go の文字は完全に utf8 と互換性があります。

go
'a'
'ä'
''
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'

エスケープ文字

Go で使用可能なエスケープ文字

\a   U+0007 ベル記号
\b   U+0008 バックスペース記号
\f   U+000C フォームフィード記号
\n   U+000A 改行記号
\r   U+000D キャリッジリターン記号
\t   U+0009 水平タブ記号
\v   U+000B 垂直タブ記号
\\   U+005C バックスラッシュエスケープ
\'   U+0027 単一引用符エスケープ (このエスケープは文字内でのみ有効)
\"   U+0022 二重引用符エスケープ (このエスケープは文字列内でのみ有効)

文字列リテラル

文字列リテラルは二重引用符 "" またはバッククォート ``(バッククォート文字列はエスケープできません)で囲む必要があります。

go
`abc`                // "abc"
`\n
\n`                  // "\\n\n\\n"
"\n"
"\""                 // `"`
"Hello, world!\n"
"今天天气不错"
"日本語"
"\u65e5\U00008a9e"
"\xff\u00FF"

関数

Go の関数宣言は func キーワードを使用して行われます。ほとんどの言語と同様です。

go
func main() {
  println(1)
}

ただし、Go の関数には 2 つの異なる点があります。1 つ目はパラメータ型が後置されることです。

func Hello(name string) {
  fmt.Println(name)
}

2 つ目の異なる点は複数の戻り値で、名前を付けることもできます。

go
func Pos() () (x, y float64) {
    ...
}

スタイル

コーディングスタイルについて、Go はすべての人に統一されたスタイルを強制します。Go 公式はフォーマットツール gofmt を提供しており、コマンドラインで使用できます。このフォーマットツールにはパラメータを渡すことができず、仅有的な 2 つのパラメータはフォーマットプロセスの出力のみです。そのため、カスタマイズは完全にサポートされておらず、このツールでフォーマットされたコードはすべて同じコードスタイルになります。これはメンテナンス担当者のメンタル負担を大幅に軽減します。そのため、この分野で個性を追求するのは賢明な選択ではありません。

以下にいくつかのルールを簡単に紹介します。コードを書く際に少し注意すると良いでしょう。

関数の波括弧の改行

関数の後の波括弧を改行するかどうかについては、ほぼすべてのプログラマーが自分なりの理由を持っていますが、Go ではすべての波括弧は改行すべきではありません。

go
// 正しい例
func main() {
  fmt.Println("Hello 世界!")
}

もし次のように書いた場合

go
// 間違いの例
func main()
{
  fmt.Println("Hello 世界!")
}

このようなコードはコンパイルさえ通らないため、Go はすべてのプログラマーに関数後の波括弧を改行しないことを強制します。

コードのインデント

Go ではデフォルトで Tab(タブ文字)を使用してインデントを行います。一部の特殊な状況でのみスペースが使用されます。

コードの間隔

Go では、ほとんどの間隔に意味があります。ある意味では、これはコンパイラがコードをどのように見ているかを表しています。例えば、以下の数学演算を見てください。

2*9 + 1/3*2

ご存知の通り、乗法の優先順位は加算よりも高いです。フォーマット後、* 記号の間隔はより紧凑になり、優先的に演算が行われることを意味します。一方、+ 記号の周辺の間隔はより大きくなり、後で演算が行われることを表しています。

波括弧の省略

他の言語では、if 文と for 文は通常省略できます。

c
for (int i=0; i < 10; i++) printf("%d", i)

しかし、Go ではできません。1 行だけ書くこともできますが、波括弧を追加する必要があります。

go
for i := 0; i < 10; i++ {fmt.Println(i)}

三項演算子

Go には三項演算子がないため、以下のコードはコンパイルできません。

go
var c = a > b ? a : b

この記事を通じて、Go の構文について初步的な理解が得られるはずです。以降のコンテンツでは、より詳しく解説していきます。

Golang学习网由www.golangdev.cn整理维护