代码仓库 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通信