最佳的学习方式就是上手实践操作!!!
本文掌握
以下为基本语法的了解,更多用法的请查看文档
- 变量声明
- 结构体
- 指针
- 方法和接收者
- 包与包间的调用
变量声明
详细请查看文档: 变量和常量
变量声明的格式,简单介绍以下几种
// var 变量名 变量类型
var name string
// 批量声明 用括号包起来
var (
name string
age int
)
// 短变量声明,在函数内部可以使用 := 初始化变量
func main() {
name := "小明"
}
指针
详细请查看文档:指针
只需要记住两个符号:&(取地址)和 *(根据地址取值)
使用请求看下面的:结构体结合指针的使用
结构体
详细请查看文档: 结构体
认识类型 type
go 有一些基本类型,如int、string、bool等
除了基本类型,我们还可以自定义类型(可以结合变量声明理解):
// 将MyInt定义为int类型
type MyInt int
结构体的定义格式
type 类型名 struct {
字段名 字段类型
字段名 字段类型
...
}
举例:
type person struct {
name string
age int8
city string
}
// 还可以这样写
type person struct {
name, city string
age int8
}
结构体实例化
声明结构类型:
// var 结构体实例 结构体类型
var p1 person
使用示例:
package main
import "fmt"
type person struct {
name string
city string
age int8
}
func main() {
var p1 person
p1.name = "李四"
p1.city = "北京"
p1.age = 18
var p2 person
p2.name = "张三"
fmt.Printf("p1=%v\n", p1) // p1={李四 北京 18}
fmt.Printf("p1=%#v\n", p1) // p1=main.person{name:"李四", city:"北京", age:18}
fmt.Printf("p2=%v\n", p2) // p2={张三 0}
fmt.Printf("p2=%#v\n", p2) // p2=main.person{name:"张三", city:"", age:0}
}
执行 go run main.go,输出对比
以上结构体可以理解为:多个字段的对象,定义为一个类型(也可以是空对象)
结构体、指针的使用
new创建指针类型结构体:
var p3 = new(person)
fmt.Printf("p3=%#v\n", p3) // p3=&main.person{name:"", city:"", age:0}
对比上面结构体实例化:
- 声明用了
= - 打印的类型 多了一个
&
使用 &对结构体取地址操作,等同于用new
p4 := &person{}
fmt.Printf("p4=%#v\n", p4) // p4=&main.person{name:"", city:"", age:0}
方法和接收者
方法的格式如下:
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
函数体
}
示例:
// Person 结构体
type Person struct {
name string
age int8
}
// NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
return &Person{
name: name,
age: age,
}
}
// Dream Person做梦的方法
func (p Person) Dream() {
fmt.Printf("%s的梦想是学好Go语言!\n", p.name)
}
// 使用指针接收者,设置age
func (p *Person) SetAge(newAge int8) {
p.age = newAge
}
func main() {
p1 := NewPerson("测试", 25)
p1.Dream()
p1.SetAge(30)
fmt.Println(p1.age) // 30
}
解读示例:
// 第一个 Person 定义结构体
// 第二个 NewPerson 构造函数
// return &Person{} 返回对结构体取地址操作
// 返回参数 *Person 根据地址取值,规范return返回参数类型, 记:&、*
// main 函数内使用:
// P1 := NewPerson("测试", 25)
// p1 就是 return &Person{} 返回, *Person 类型的结构体
// 第三个 Dream 构造函数
// (p Person)
// p 接收者 Person类型,对比 SetAge
// 第四个 SetAge 构造函数
// (p *Person)
// p 指针接收者 *Person指针类型,这里对接收者的内容做了设置更新,所以需要用指针接收者,指针根据地址取值,对 P1 的值做设置
// p1.SetAge(30)
包与包间的调用
以上都是在 main.go 入口文件单文件中操作
如果根据以下目录这么包与包间的调用呢?
├── gin 为项目根目录
│ ├── Router 为路由目录
│ └── router.go
│ ├── Models 为模型目录
│ └── personModel.go
└── main.go 为入口文件
根据上面这个目录结构
项目升级
这里需要再提下,下面有用到:
入门二
依赖包管理初始化命令 go mod init xxx
入门三
邂逅gin框架 中路由的配置,下面把路由设置移到router.go文件
对应文件内容如下:
// router.go
package router
import (
"net/http"
"github.com/gin-gonic/gin"
)
func SetInit() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello world")
})
r.GET("gintest", func(c *gin.Context) {
c.String(http.StatusOK, "gin test")
})
r.Run(":3250")
}
// personModel.go
package models
import "fmt"
type Person struct {
Name string `json:"name"`
Age int8 `json:"age"`
}
// NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
return &Person{
Name: name,
Age: age,
}
}
// Dream Person做梦的方法
func (p Person) Dream() {
fmt.Printf("%s的梦想是学好Go语言!\n", p.Name)
}
// 使用指针接收者,设置age
func (p *Person) SetAge(newAge int8) {
p.Age = newAge
}
// main.go
package main
import (
"fmt"
router "gin/Router"
"gin/models"
)
func main() {
p1 := models.NewPerson("测试", 25)
p1.Dream()
p1.SetAge(30)
fmt.Println(p1.Age)
router.SetInit()
}
解释上面包与包间的调用
// router.go 文件
//router 为当前包名称
package router
// `persomModel.go 文件
// models 为当前包名称
package models
// main.go
// 应用本地包
import (
router "gin/Router"
"gin/models"
)
// router 为 router.go 定义的包名称
// "gin/Router"
// gin: 为 go mod init XXX 依赖包管理初始化设置的 XXX,
// /Router: 包在项目中距根目录的路径
// 这样就可以调用router包里的方法执行 -> router.SetInit()
// "gin/models" 使用同上
// 调用models包里的方法 -> models.NewPerson("测试", 25)
"gin/Router" 中的 gin 为 go mod init XXX 依赖包管理初始化设置的 XXX,这也是可以修改的,在go.mod文件修改 module gin
调用router包里的方法执行 -> router.SetInit()
最后可正常运行的项目目录应该是下面这样的,多了两个文件 go.mod、go.sum
├── gin 为项目根目录
│ ├── Router 为路由目录
│ └── router.go
│ ├── Models 为模型目录
│ └── personModel.go
├── go.mod go mod init xxx 生成的包管理模块
├── go.sum go get github.com/xxx 下载包生成
└── main.go 为入口文件
按这样的执行 go run main.go
$ go run main.go
测试的梦想是学好Go语言!
30
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET / --> gin/Router.SetInit.func1 (3 handlers)
[GIN-debug] GET /gintest --> gin/Router.SetInit.func2 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :3250
项目启动成!!!
完结
撒花~,入门系列学完了~
再续征程
进阶可以看下 go-gin-example 这个开源项目
再往前,就要靠你自己了,朋友加油!