安装

由于篇幅有限, 请参考网络上的教程

代码仓库

gitee

如何运行

以打印hello world为例

1
2
3
4
5
6
7
8
// main.go
package main // 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 main

import "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
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)
}
}

函数

函数的本质是一个闭包, 有自己的作用域
我们可以用函数定义一段代码, 接收0或多个输入, 执行函数体内的代码, 在结束时返回0或多个输出
使用函数可以提取公共逻辑, 简化我们的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "fmt"

// 定义一个函数,接收两个整数参数,返回它们的和
func add(a int, b int) int {
return a + b
}

func main() {
result := add(5, 3)
fmt.Println("Result:", result) // 输出: Result: 8
}

类/结构体

类/结构体

类是一个包含了数据和方法(函数)的抽象结构, 我们可以定义它, 要使用类, 需要将类实例化, 其实就是在内存中开辟指定大小的空间来保存它
类的大小取决于内部定义什么数据(比如int), 编译器会自动根据数据大小来决定分配多少空间
一个类可以有多个实例化对象, 也就是有多个不同变量, 但是这些变量都和这个类的结构一致

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"

// 定义一个结构体 Person,包含 Name 和 Age 字段
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
50
package main

import "fmt"

// 定义一个接口 Animal,包含一个 Speak 方法
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框架, 就是封装了语言本身提供的网络库,
然后提供了开放网络服务的各种方法
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 main

import (
"github.com/gin-gonic/gin"
)

func main() {
// 创建一个默认的路由引擎
r := gin.Default()

// 定义一个 GET 接口
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello from Gin!",
})
})

// 启动 HTTP 服务,默认在 0.0.0.0:8080
r.Run(":8080")
}

访问localhost:8080/hello查看

db

我们目前都是使用变量来存储数据, 但是变量的数据是放在内存中的, 一旦程序停止, 内存中的数据就会被回收, 下一次启动程序,
操作系统分配的也可能是另一个内存空间, 所以我们需要持久化存储我们的数据, 这就需要用到数据库系统

go语言常用的数据库框架为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 main

import (
"github.com/glebarez/sqlite"
// 需要 go env -w CGO_ENABLED=1
// 并且需要gcc, 不过这个是官方实现, 比较好
// "gorm.io/driver/sqlite"
"gorm.io/gorm"
)

// 定义一个结构体,对应数据库表
type User struct {
gorm.Model
Name string
Email string `gorm:"unique"`
}

func main() {
// 连接 SQLite 数据库(文件名为 test.db)
db, err := gorm.Open(sqlite.Open("./dev.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}

// 自动迁移 schema
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/grpc

社群

你可以在这些平台联系我:


本站总访问量