基础阶段学习知识
21天精通Go语言 :推荐两倍速观看
Go语言学习博客 上述B站视频的对应博客
go语言编程基础
Go by Example 中文版
golang学习图谱
go语言基本语法
- 变量声明后必须使用,否则不会编译通过,全局变量除外
- 变量赋值的三种方式
//第一种
var name string = "Alice"
//第二种
var name = "Alice"
//第三种,只能在函数中使用
name := "Alice"
- 匿名变量用一个下划线"-"表示
iota
关键字是按照行来计数的,每增加一行就会加1float
默认类型是float64
,float32
和float64
之间不能相互赋值- 字符串相关操作
str := "哈哈哈,I am a student"
s1 := []rune(str) //把字符串强制转换为一个run切片
s1[1] = '中'
fmt.Println(string(s1)) //将切片转换为字符串,输出为 哈中哈,I am a student
rune
在本质上是一个int32
类型的- go中没有关键字char,字符型也是
int32
- go中没有while关键字,只有for循环
- 可以使用
for range
遍历数组、切片、字符串、map及通道 - 初始化数组
arr := [...]int{1,2,3,4,5,6,7,8,9,10}
- 数组是值类型,不是引用类型,所以支持
==
和!=
运算符
strings包
随机数
func main() {
rand.Seed(time.Now().UnixNano()) //生成随机数种子
fmt.Println(rand.Int())
}
函数
函数作为参数和返回值
import "fmt"
func main() {
function(f1)
}
func f1() int {
return 10
}
func function(x func() int) func(int,int) int{
ret := func(a,b int) int{
return a+b
}
return ret
}
上述函数function
的传入参数可以是函数,但这个函数的返回值需要是int
类型;function
的返回值也是函数,返回的这个函数需要满足两个int类型参数,和int类型返回值
匿名函数
- 在函数结尾加
()
表示立即执行,一般适用于只使用一次的情况
func main() {
f1 := func(a,b int) {
println(a+b)
}
f1(2,3)
func(a,b int){
println(a+b)
}(1,2)
}
闭包
- 闭包是一个函数,此函数包含了外部作用域的一个变量
func f1(f func()) {
fmt.Println("f1执行了")
}
func f2(x,y int) {
fmt.Println("f2执行了")
fmt.Println(x+y)
}
//f3 修改后的函数
func f3(f func(int,int),x,y int) func() {
tmp := func() {
//fmt.Println(x+y)
f(x,y)
}
return tmp
}
高级语法
切片
本篇博文不错
切片(Slice
)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。切片是一个引用类型
,它的内部结构包含地址、长度和容量。切片一般用于快速地操作一块数据集合。和数组的区别在于数组的复制为值复制
,切片的复制为引用复制
。
- 切片的容量是指 从切片的第一个元素开始到最后的元素的容量
//切片声明
var name []T
//make函数构造切片
make([]T, size, cap)
//slice内部节后
type SliceHeader struct{
Data uintptr
Len int
Cap int
}
/*
T:切片的元素类型
size:切片中元素的数量
cap:切片的容量
*/
切片的扩容原理:代码在src/runtime/slice.go
下
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
- 首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)。
- 否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap),
- 否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
- 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)。
包管理
若需要访问不同包下的func、type、变量及常量,需要将
变量名首字母大写
若要访问不同包结构体下的字段,需要将字段变量名首字母大写
反射
作用:Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。
Go语言的反射主要是通过Type和Value两个基本概念进行实现的,实现主要位于
reflect
包下
Type
:反射变量的类型信息
Value
:反射变量自身的实例信息
gin框架传输json数据两种形式
r.GET("/hello", func(c *gin.Context) {
//方式1 使用map进行序列化
data := map[string]interface{}{
"name":"root",
"age":"12",
}
data := gin.H{"name":"root","age":18}
c.JSON(http.StatusOK, data)
//方式2 定义结构体
var data struct{
Name string
Age int `json:"afe"` //go要求返回字符必须首字母大写,使用这种方式可以在json取值时返回首字母小写
Message string
}
data.Message = "hello"
data.Age = 18
data.Name = "hai"
c.JSON(http.StatusOK,data)
})