ethan

ethan

新知,热爱生活,码农,读书
twitter
email
github

Go言語の基礎

Go 言語の基礎:変数と定数#

変数と定数はプログラミングにおいて不可欠な部分であり、理解しやすい部分でもあります。

## 識別子とキーワード

識別子#

プログラミング言語における識別子とは、プログラマーが定義した特別な意味を持つ単語のことです。例えば、変数名、定数名、関数名などです。Go 言語の識別子は、英数字と_(アンダースコア) で構成され、必ず文字または_で始まる必要があります。

キーワード#

キーワードとは、プログラミング言語においてあらかじめ定義された特別な意味を持つ識別子のことです。キーワードや予約語は変数名として使用することは推奨されません。Go 言語には 25 のキーワードがあります。

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 言語には 37 の予約語があります。

Constants: true false iota nil
Types: int int8 int16 int32 int64
        uint uint8 uint16 uint32 uint64 uintptr
        float32 float64 complex128 complex64
        bool byte rune string error
Functions: make len cap new append copy close delete
            complex real imag
            panic recover

変数#

変数の由来#

プログラムの実行中に扱うデータはすべてメモリに保存されます。コード内で特定のデータを操作したい場合、その変数をメモリ上で見つける必要があります。しかし、メモリアドレスを直接コード内で操作すると、コードの可読性が非常に低下し、エラーが発生しやすくなります。そこで、変数を利用してデータのメモリアドレスを保存し、以後はその変数を通じてメモリ上の対応するデータを見つけることができます。

変数の型#

変数の機能はデータを保存することです。異なる変数は異なるデータ型を保存することがあります。Go 言語のすべての変数には独自の型があり、変数は宣言されて初めて使用できます。

変数の宣言#

Go 言語の変数は宣言後に使用する必要があります。同一のスコープ内での重複宣言はサポートされていません。また、Go 言語の変数は宣言後に必ず使用されなければなりません。

標準宣言#

Go 言語の変数宣言の形式は次の通りです:

var 変数名 変数型

変数宣言はキーワード var で始まり、変数型は変数の後に置かれ、行末にセミコロンは不要です。

型推論#

時には変数の型を省略することがあります。この場合、コンパイラは等号の右側の値に基づいて変数の型を推論し、初期化を完了します。

var name = "Q1mi"
var ag=18

短い変数宣言#

関数内部では、より簡略な := 形式を使用して変数を宣言し初期化できます。

package main
import (
    "fmt"
)
//グローバル変数m
var m = 10

func main() {
    n := 10
    m := 200 // ここでローカル変数mを宣言
    fmt.Println(m, n)
}

匿名変数#

複数の値を代入する際に、特定の値を無視したい場合は匿名変数を使用できます。匿名変数はアンダースコア_で表されます。

func foo()(int, string) {
    return 10, "Q1mi"
}
func main() {
    x, _ := foo()
    _, y := foo()
    fmt.Println("x=", x)
    fmt.PrintLn("y=", y)
}

匿名変数は名前空間を占有せず、メモリを割り当てないため、匿名変数同士の重複宣言は存在しません。
注意事項:

  1. 関数外の各文は必ずキーワードで始まる必要があります(var, const, func など)。
  2. := は関数外では使用できません。
  3. _ は主にプレースホルダーとして使用され、値を無視することを示します。

定数#

変数に対して、定数は不変の値であり、プログラムの実行中に変更されない値を定義するのに多く使用されます。定数の宣言は変数の宣言と非常に似ていますが、varconst に置き換え、定義時に必ず値を割り当てる必要があります。そして、プログラムの実行中、これらの値は変更されることはありません。

iota#

iota は Go 言語の定数カウンターで、定数の式内でのみ使用できます。iota は const キーワードが出現すると 0 にリセットされます。Const 内に新しい行の定数宣言が追加されるたびに、iota は 1 回カウントされます(iota は const 文ブロック内の行インデックスと理解できます)。iota を使用すると定義が簡素化され、列挙を定義する際に非常に便利です。

論理演算子#

演算子説明
&&論理 AND 演算子。両方のオペランドが True の場合は True
||論理 OR 演算子
!論理 NOT 演算子

変数のスコープ#

グローバル変数は大文字で始まり、すべての場所からアクセス可能で、パッケージを跨いでアクセスするにはパッケージ名を付ける必要があります。小文字で始まるグローバル変数は、本パッケージ内でのみアクセス可能です。ローカル変数は、その関数内でのみアクセス可能です。内部で宣言された変数は外部で宣言された変数と衝突する可能性があり、内部のものが優先されます。{} で囲まれたスコープ内でのみアクセス可能で、外部の変数と衝突することがあります。

変数のライフサイクル#

変数のライフサイクルは、プログラムの実行中に有効に存在する時間の間隔を指します。パッケージレベルで宣言された変数のライフサイクルは、プログラム全体の実行周期と一致します。一方、ローカル変数のライフサイクルは動的です:新しい変数の宣言文が作成されるたびに始まり、その変数が参照されなくなるまで続きます。その後、変数のストレージスペースは回収される可能性があります。
注意:

  • 変数の有効周期は到達可能性にのみ依存するため、ループの反復内のローカル変数のライフサイクルはそのローカルスコープを超える可能性があります。また、ローカル変数は関数が返された後も存在することがあります。

Go 言語の基礎:基本データ型とコメント#

Go 言語には豊富なデータ型があり、基本的な整数型、浮動小数点型、ブール型、文字列の他に、配列、スライス、構造体、関数、マップ、チャネルなどがあります。Go 言語の基本型は他の言語と大差ありません。

基本データ型#

整数型#

整数型は以下の 2 つの大きなカテゴリに分かれます:長さによって分けられ、int 8、int 16、int 32、int 64 に対応する符号なし整数型:uint 8、uint 16、uint 32、uint 64 の中で、uint 8 は私たちがよく知っている byte 型です。int 16 は C 言語の short 型に、Int 64 は C 言語の long 型に対応します。

説明
uint 8符号なし 8 ビット整数型 (0-255)
uint 16符号なし 16 ビット整数型 (0-65535)
uint 32符号なし 32 ビット整数型 (0-4294967295)
uint 64符号なし 64 ビット (0-18446744073709551615)
int 8符号付き 8 ビット整数型 (-128-127)
int 16符号付き 16 ビット整数型 (-32768 から 32767)
int 32符号付き 32 ビット整数型 ()

ブール値#

Go 言語では bool 型を使用してブール型データを宣言します。ブール型データは truefalse の 2 つの値のみを持ちます。
注意:

  1. ブール型変数のデフォルト値は false です。
  2. Go 言語では整数型を強制的にブール型に変換することは許可されていません。
  3. ブール型は数値演算に参加できず、他の型に変換することもできません。

文字列#

Go 言語の文字列はネイティブデータ型として登場し、文字列の使用は他のネイティブデータ型(int、bool、float 32、float 64 など)と同様です。Go 言語の文字列の内部実装は UTF-8 エンコーディングを使用しています。文字列の値は ダブルクォーテーション(") 内の内容であり、Go 言語では ASCII 以外の文字を直接追加することができます。例えば:

s1 := "hello"

文字列の一般的な操作#

メソッド説明
len (str)長さを求める
+ または fmt.Sprintf文字列を結合する
strings.Split分割する
strings.Contains含まれているか判断する
strings.HasPrefix、strings.HasSuffixプレフィックス / サフィックスの判断
strings.Index()、strings.LastIndex()サブ文字列の出現位置
strings.Join(a[] string, sep String)join 操作

Byte と rune 型#

各文字列を構成する要素は「文字」と呼ばれ、文字列要素を反復処理または単独で取得することで得られます。文字はシングルクォーテーション(‘)で囲まれます。例えば:

var a := ''
var b ::= 'x'
// byteはuint8と等価、runeはint32と等価です
// runeは任意のunicode文字を表すことができます

複合データ型#

デフォルト値説明
array値型
struct値型
string""UTF-8 文字列
slicenil参照型
mapnil参照型
channelnil参照型
interfacenilインターフェース
functionnil関数

配列#

配列は連続したメモリ空間であり、宣言時に長さを指定する必要があり、長さは変更できません。したがって、配列は宣言時にメモリ空間を割り当て、デフォルト値を設定することで初期化を完了できます。

配列の初期化#

var arr [5]int = [5]{} // 配列は長さと型を指定する必要があり、長さと型が指定された後は変更できません
var arr2 = [5]int{}
var arr3 = [5]int{3,2} // 最初の2つの要素に値を設定
var arr4 = [5]int{2:15, 4:30} // インデックスを指定してコピー
var arr5 = [...]int{3,2,6,5,4} // {}内の要素の数に基づいて配列の長さを推測
var arr6 = [...]struct{
name string
age int
}{{"Tome", 18}, {"Jim", 20}} // 配列の要素の型は匿名構造体によって指定されます

配列内の要素へのアクセス#

  • インデックスを通じてアクセス

    • 最初の要素 arr [0]
    • 最後の要素 arr [len (arr)-1]
  • 二次元配列内の要素へのアクセス

    • 第 3 行第 4 列の要素 arr [2][3]

      // 配列内の要素を反復処理
      for i, ele := range arr {
      fmt.Printf("index=%d, element=%d\n", i, ele)
      }
      // 二次元配列を反復処理
      for row, array := range arr {
      for col, ele := range array {
        fmt.Printf("arr[%d][%d]=%d\n", row, col, ele)
      }
      }
      

      cap と len#

  • Cap は容量を表します。

  • Len は長さを表します。

  • len は現在の配列内の要素数を表し、cap は配列に割り当てられたメモリ空間がいくつの要素を収容できるかを表します。

  • 配列は初期化後に変更されないため、メモリ空間を事前に予約する必要がないため、len (arr) = cap (arr) となります。

    配列の引数渡し#

  • 配列の長さと型は配列型の一部であり、関数に配列型を渡す際には、これらの 2 つの部分が一致する必要があります。

  • Go 言語には参照渡しはなく、すべて値渡しです。つまり、配列を渡すと実際には配列のコピーが送られます。配列の長さが非常に大きい場合、単に引数を渡すだけでも大きなオーバーヘッドが発生します。

  • 関数外の配列を変更したい場合は、そのポインタ(メモリ内の配列のアドレス)を渡します。

スライス#

type slice struct {
    array unsafe.Pointer
    len int
    cap int 
}

スライスの初期化#

var s []int // スライスの宣言、len=cap=0
s = []int{} //初期化、 len=cap=0
s = make([]int, 3) //初期化、 len=cap=3
s = make([]int, 3, 5) //初期化,len=3, cap=5
s = []int{11,2,3,4,5} //初期化、 len=cap=5
s2d := [][]int {
{1}, {2,3},  // 二次元配列は各行の列数が等しいが、二次元スライスは各行のlenが異なることができます
}

Append#

  • スライスの最大の特徴は、要素を追加でき、自動的に拡張されることです。

  • 追加された要素は予約されたメモリ空間に配置され、同時に len が 1 増加します。

  • 予約されたスペースが使い果たされた場合、より大きなメモリ空間を再度要求し、capacity は以前の 2 倍(cap<1024)または 1.25 倍(cap>1024)になります。元のメモリ空間のデータをコピーし、新しいメモリ空間で append 操作を実行します。

    サブスライスの取得#

  • s := make([]int, 3,5) // len=3, cap=5

  • sub_slice = s[1:3] // len = 2, cap=4

  • 最初は、サブスライスと母スライスは底層のメモリ空間を共有しており、サブスライスを変更すると母スライスにも反映されます。サブスライスで append を実行すると、母スライスの予約されたメモリ空間に新しい要素が配置されます。

  • サブスライスが append を繰り返し実行し、母スライスの予約されたメモリ空間を使い果たすと、サブスライスと母スライスはメモリが分離され、2 つのスライスはもはや関係がなくなります。

スライスの引数渡し#

  • Go 言語の引数渡しはすべて値であり、スライスを渡すとスライスの {arrayPointer, len, cap} の 3 つのフィールドがコピーされます。

  • 底層配列のポインタが渡されるため、底層配列内の要素を直接変更できます。

    マップ#

    マップは無秩序な key/value ペアの集合であり、すべての key は異なり、指定された key を使用して定数時間の複雑さで対応する value を検索、更新、または削除できます。

ポインタ#

定義#

カスタム型と文字列#

  • 型エイリアス

    • Type byte = uint 8
    • Type rune = int 32
  • カスタム型

    • type signal uint 8

    • Type ms map[string]string

    • Type add func (a, b int) int

    • Type user struct {name string; age int}

      強制型変換#

      var i int = 9
      var by byte = byte(i)  // intをbyteに変換
      i = int(by)  // byteをIntに変換
      fmt.Printf("i=%d\n", i)
      
  • Byte と int は相互に変換可能です。

  • Float と int は相互に変換可能で、小数点以下は失われます。

  • Bool と int は相互に変換できません。

  • 異なる長さの int または float は相互に変換可能です。

  • String は [] byte または [] rune 型に変換でき、byte または rune は string に変換できます。

  • 低精度から高精度への変換は問題ありませんが、高精度から低精度への変換はビット数が失われます。

  • 符号なしから符号付きへの変換では、最上位ビットが符号ビットになります。

    コメント#

  • 単一行コメント。// で始まります。

  • 複数行コメント。連続した複数行は // で始めるか、ブロックの前に /* を使用し、ブロックの後に */ を使用します。

  • 複数行コメントの間に空行を入れてはいけません。

  • NOTE: 注意が必要、TODO:将来的に最適化が必要、Deprecated: 変数または関数は使用しないことを強く推奨します。

  • コメント行の前にインデントを追加することで Go コードを書くことができます。

  • パッケージコメント。package xxx の上に書きます。1 つのパッケージには 1 箇所にパッケージコメントを書く必要があり、通常は doc.go に書かれ、そこには package xxx とパッケージに関するコメントが 1 行だけあります。

  • 構造体コメント。type xxx struct の上に書きます。

  • 関数コメント。func xxx () の上に書きます。

  • 行コメント。行の上または右側に書きます。

    Godoc#

  • Go doc は Go に付属のコマンドです。

  • Go doc entrance class/util

  • Go doc はプロジェクトコードのウェブ版コメントドキュメントをエクスポートできます。

  • まず、go get golang.org/x/tools/cmd/godoc をインストールする必要があります。

  • http: godoc -http:6060 を起動します。

  • ブラウザでアクセス: http://127.0.0.1:6060/pkg/go-course/entrans_class

パッケージとツール#

パッケージ#

パッケージの概要#

  • すべてのインポートされたパッケージは、各ファイルの先頭で明示的に宣言する必要があります。

  • パッケージの循環依存は禁じられています。循環依存がないため、パッケージの依存関係は有向非循環グラフを形成し、各パッケージは独立してコンパイルでき、並行してコンパイルされる可能性があります。

  • コンパイル後のパッケージのターゲットファイルは、パッケージ自体のエクスポート情報だけでなく、パッケージの依存関係も記録します。

    インポートパス#

    各パッケージは、グローバルに一意の文字列で識別されるインポートパスによって位置付けられます。import 文に出現するインポートパスも文字列です。Go 言語の規範は、パッケージのインポートパス文字列の具体的な意味を明示していません。インポートパスの具体的な意味はビルドツールによって解釈されます。

    パッケージ宣言#

    各 Go 言語ソースファイルの先頭にはパッケージ宣言文が必要です。パッケージ宣言文の主な目的は、現在のパッケージが他のパッケージにインポートされたときのデフォルトの識別子(パッケージ名とも呼ばれます)を決定することです。

    パッケージと命名#

  • パッケージ名には、ローカル変数として頻繁に使用される可能性のある名前を使用しないようにしてください。これにより、ユーザーがインポートパッケージの名前を変更する可能性があります。

  • パッケージ名は一般的に単数形を使用します。標準ライブラリの bytes、errors、strings は複数形を使用しており、これは事前定義された型との衝突を避けるためです。同様に、go/types は type キーワードとの衝突を避けるためです。

    ツール#

    Go 言語のツールボックスは、一連の機能コマンドの集合です。これは、パッケージのクエリ、パッケージの依存関係の計算、リモートバージョン管理システムからのダウンロードなどのタスクを実行するためのパッケージ管理システムとして考えることができます。また、ビルドシステムとして、ファイルの依存関係を計算し、コンパイラ、アセンブラ、リンカを呼び出してプログラムを構築します。また、単体テストやベンチマークテストのドライバーでもあります。

パッケージのダウンロード#

Go 言語ツールボックスの go コマンドを使用すると、パッケージのインポートパスに基づいてローカル作業スペースのパッケージを見つけるだけでなく、インターネット上のパッケージも見つけて更新できます。

go getコマンドを使用して、単一のパッケージをダウンロードすることも、...を使用してサブディレクトリ内のすべてのパッケージをダウンロードすることもできます。Go 言語ツールボックスの go コマンドは、依存する各パッケージを計算してダウンロードします。

一度go getコマンドがパッケージをダウンロードすると、次はパッケージまたはその対応する実行可能プログラムをインストールします。

パッケージのビルド#

go buildコマンドは、コマンドライン引数で指定された各パッケージをコンパイルします。パッケージがライブラリである場合、出力結果は無視されます。これは、パッケージが正しくコンパイルできるかどうかを検出するために使用できます。パッケージ名が main の場合、go buildはリンカを呼び出して現在のディレクトリに実行可能プログラムを作成します。実行可能プログラムの名前はインポートパスの最後の部分になります。

各ディレクトリには 1 つのパッケージしか含まれないため、各対応する実行可能プログラム、または Unix 用語でのパッケージは、独立したディレクトリに配置する必要があります。

インターフェース#

インターフェース型は他の型の動作を抽象化し、概括するものです。インターフェース型は特定の実装の詳細にバインドされないため、この抽象化の方法により、私たちの関数はより柔軟で適応性を持つことができます。Go 言語のインターフェース型の独自の点は、暗黙的な実装を満たすことです。つまり、特定の型に対してすでに存在する具体的な型を満たすために、すべてを定義する必要はありません。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。