代码仓库 gitee
実行方法 Hello Worldを例に取って実行方法を説明します。
1 2 3 4 5 6 7 8 package main import "fmt" func main () { fmt.Println("Hello, World!" ) }
1 2 3 4 5 # 直接実行 go run main.go # またはコンパイルして実行 go build main.go ./main.exe
変数定義とデータ型 変数はメモリ上の特定のアドレスを指す識別子で、通常データを保存するために使用されます。 データ型は変数の型を表し、型はメモリ上でその変数が占めるスペースの大きさを決定します。 代入はデータ(値)を変数が指すアドレスに保存し、後でその変数を使ってそのデータにアクセスします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport "fmt" func main () { var age int = 25 fmt.Println("Age:" , age) var height float64 = 1.75 fmt.Println("Height:" , height) var name string name = "Alice" fmt.Println("Name:" , name) isStudent := true fmt.Println("Is student:" , isStudent) }
フロー制御 フロー制御とはプログラムの実行順序を定義することです。
順序 順序実行は上から下へと順番に実行されます。これはプログラムの通常の実行フローです。
1 2 3 4 5 6 7 8 9 package main import "fmt" func main() { fmt.Println("Step 1") fmt.Println("Step 2") fmt.Println("Step 3") }
選択 選択とは異なる条件に基づいて異なるコードを実行することです。 選択のフローは単一分岐と多分岐に分けられます。
単一分岐 単一分岐とは1つの分岐ノードしかなく、1回の条件判断しかありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package main import "fmt" func main() { var score int = 85 if score >= 60 { fmt.Println("Pass") } else { fmt.Println("Fail") } }
多分岐 多分岐とは複数の分岐ノードがあり、複数の条件判断があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package main import "fmt" func main() { var score int = 85 if score >= 90 { fmt.Println("A") } else if score >= 80 { fmt.Println("B") } else if score >= 70 { fmt.Println("C") } else { fmt.Println("D") } }
ループ ループは繰り返し実行されるプロセスを表します。
1 2 3 4 5 6 7 8 9 10 11 package main import "fmt" func main() { // 一時変数iを定義し、初期値を1に設定し、ループ条件をiが5以下であるとする for i := 1; i <= 5; i++ { fmt.Println(i) } }
関数 関数はクロージャであり、独自のスコープを持ちます。 関数は1つ以上の入力を受け取り、関数体のコードを実行し、終了時に1つ以上の出力を返すことができます。 関数を使用することで、共通のロジックを抽出し、コードを簡素化することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package main import "fmt" // 2つの整数パラメータを受け取り、それらの和を返す関数を定義 func add(a int, b int) int { return a + b } func main() { result := add(5, 3) fmt.Println("Result:", result) // 出力: Result: 8 }
クラス/構造体 クラス/構造体 クラスはデータとメソッド(関数)を含む抽象構造であり、それを定義することができます。 クラスを使用するには、クラスをインスタンス化する必要があります。これは、指定されたサイズのメモリ空間を確保して保存することです。 クラスのサイズは内部で定義されたデータ(例えばint)によって決まり、コンパイラはデータのサイズに基づいて必要なメモリを自動的に割り当てます。 1つのクラスには複数のインスタンス化オブジェクトがあり、つまり複数の異なる変数がありますが、これらの変数はすべて同じクラスの構造を持ちます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package main import "fmt" // NameとAgeフィールドを含むPerson構造体を定義 type Person struct { Name string Age int } // PersonにSayHelloメソッドを追加 func (p Person) SayHello() { fmt.Printf("Hello, my name is %s and I am %d years old.\n", p.Name, p.Age) } func main() { // Personインスタンスを作成 person := Person{Name: "Alice", Age: 25} // メソッドを呼び出す person.SayHello() // 出力: Hello, my name is Alice and I am 25 years old. }
インターフェース 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package main import "fmt" // Speakメソッドを含むAnimalインターフェースを定義 type Animal interface { Speak() string // Speak()メソッドを実装したすべての型はAnimal型と見なされる } // Dog構造体を定義 type Dog struct { Name string } // DogにSpeakメソッドを実装 func (d Dog) Speak() string { return "Woof! My name is " + d.Name } // Cat構造体を定義 type Cat struct { Name string } // CatにSpeakメソッドを実装 func (c Cat) Speak() string { return "Meow! My name is " + c.Name } func main() { // Animalインターフェース変数を宣言 var a Animal // Dogインスタンスを作成 dog := Dog{Name: "Buddy"} a = dog // DogがAnimalインターフェースを実装しているため、aに代入できる fmt.Println(a.Speak()) // 出力: Woof! My name is Buddy // Catインスタンスを作成 cat := Cat{Name: "Whiskers"} a = cat // Catも同様にAnimalインターフェースを実装している fmt.Println(a.Speak()) // 出力: Meow! My name is Whiskers // 異なる型のオブジェクトを統一的に処理できる animals := []Animal{dog, cat} for _, animal := range animals { fmt.Println(animal.Speak()) } }
フレームワーク 開発を簡素化するために、プログラマは共通のロジックを関数やクラス・メソッドにカプセル化して再利用します。このような抽象化が進むと「フレームワーク」が生まれます。 私の理解では、「ライブラリ(library)」とは共通機能を集めたツール群であり、ユーザーが必要に応じて任意のものを追加して使用できるものです。一方で「フレームワーク(framework)」は、プロジェクトにおける構造やテンプレートを定義し、そのルールに従ってユーザーが開発を行うというスタイルに近いです。ただし、実際にはこの二つの境界は曖昧な場合が多く、混同されて使われることも頻繁にあります。
Web これまで作成してきたプログラムはすべてローカルで動作していますが、世界中のユーザーにも使えるようにするにはネットワーク上に公開する必要があります。 Webフレームワークは言語標準のネットワーク機能をラップし、HTTPサーバー構築やルーティングなどの機能を提供します。 Go言語でよく使われるWebフレームワークは Gin です。
1 go get "github.com/gin-gonic/gin"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package mainimport ( "github.com/gin-gonic/gin" ) func main () { r := gin.Default() r.GET("/hello" , func (c *gin.Context) { c.JSON(200 , gin.H{ "message" : "Hello from Gin!" , }) }) r.Run(":8080" ) }
ブラウザで http://localhost:8080/hello にアクセスして確認してください。
DB(データベース) 現在までは変数を使ってデータをメモリ内に保存してきましたが、プログラム終了と同時にメモリ上のデータは破棄されてしまいます。そのため、データを永続的に保持したい場合には「データベース」が必要になります。 Go言語でよく使われるORM型データベースフレームワークは GORM です。
1 go get "gorm.io/driver/sqlite" "gorm.io/gorm" "github.com/glebarez/sqlite"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package mainimport ( "github.com/glebarez/sqlite" "gorm.io/gorm" ) type User struct { gorm.Model Name string Email string `gorm:"unique"` } func main () { db, err := gorm.Open(sqlite.Open("./dev.db" ), &gorm.Config{}) if err != nil { panic ("failed to connect database" ) } db.AutoMigrate(&User{}) db.Create(&User{Name: "Alice" , Email: "alice@example.com" }) var user User db.Where("name = ?" , "Alice" ).First(&user) println ("Found user:" , user.Name) db.Model(&user).Update("Name" , "Bob" ) db.Delete(&user) }
拡張機能の例 ○ 並列処理(ゴルーチン)、マイクロサービスアーキテクチャ、リフレクション(動的プロキシ生成)、ファイル操作、ネットワーク通信など ○ フレームワークの内部原理と自作 ○ WASM(WebAssembly)、gRPCによるRPC通信