总结了一下本人看go语言时关注的一些点,适合有基础的人交流
!! 如果你要快速看懂go代码,可以往下看,如果想要系统学习go语言建议大家可以看 https://www.jianshu.com/p/5ee783bbdcac !!
一、变量声明
var 变量名 变量类型
var (
变量名 变量类型
变量名 变量类型
变量名 变量类型
)
指针: var 变量名 new(类型名)
数组: var 变量名 []类型名
结构体: 实例名 struct{
变量名 变量类型
}
二、变量初始化
var aaa= 40 //编译器会根据40猜你的aaa类型
var damageRate float32 = 0.17 //正常赋值
aaa := 40 //更简单的写法,不用形式上定义一下aaa, := 就相当于定义加赋值,
1.已定义过的变量不能用 := 进行赋值
2.:= 可以一次性定义多个变量并赋值
eg. conn, err := net.Dial("tcp", "127.0.0.1:8080")
conn2, err := net.Dial("tcp", "127.0.0.1:8080")
net.Dial 返回了两个值,分别赋值给了 conn和err。
(conn, err) 和 (conn2, err) , 这两组变量,只要每组有一个是新变量就可以通过,编译器不会报错
3.多变量赋值 func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
这个例子就很直观了,多变量赋值从左到右依次赋值,并不care你是谁
4. 对函数定义有疑问的,看看下面几个例子应该就差不多了
type IntSlice []int
func (p IntSlice) Len() int { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
作用范围不止在函数里面的放到前面括号里,作用范围只在函数里面的放到后面括号里
5.匿名变量 _,b := GetData() 不在乎这个变量是谁,用_占个位置就行
如果只需要前面的变量 a := GetData() 就行
三、字符串
str :=“注意字符串转义符就行了”
1.utf8编码
2.多行字符串输入
ch := ` 第一行
第二行
第三行
`
两边加的这个是反引号,键盘1旁边那个
四、字符
uint8 等价于 byte
rune 等价于 int32,代表一个 UTF-8 字符。当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。
五、类型转换
var c float32 = math.Pi
fmt.Println(int( c))
别的转换方式 fmt.Printf("int32: 0x%x %d\n", c, c)
六、指针
var a = 111
ptr := &a //定义
value := *ptr //引用
1.有指针的交换函数就要借助中间变量,不能再像 【二、3 】 说明的那样直接赋值
2.创建指针的另一种方式 var ptr=new(int)
七、变量逃逸
简单来说,这个变量已经不存在了,但是你还是使用了他,那么这个变量就是逃逸的变量
package main
import "fmt"
// 声明空结构体测试结构体逃逸情况
type Data struct {
}
func dummy() *Data {
// 实例化c为Data类型
var c Data
//返回函数局部变量地址
return &c
}
func main() {
fmt.Println(dummy())
}
比如上面例子里的 c指针,原来的C编程,这里已经越界访问了,但是go里有变量逃逸,我们的c指针就逃逸成功了
变量逃逸不只是指针类型,上面如果return c ,整型,那么c也是一个逃逸到堆内存的变量
八、const
很简单了
const aa=1
const(
aa=1
bb=2
)
下面给一个 const 模拟枚举类的例子
type Weapon int
const (
Arrow Weapon = iota // 开始生成枚举值, 默认为0
Shuriken
SniperRifle
Rifle
Blower
)
// 输出所有枚举值
fmt.Println(Arrow, Shuriken, SniperRifle, Rifle, Blower)
// 使用枚举类型并赋初值
var weapon Weapon = Blower
fmt.Println(weapon)
const (
FlagNone = 1 << iota
FlagRed
FlagGreen
FlagBlue
)
fmt.Printf("%d %d %d\n", FlagRed, FlagGreen, FlagBlue)
fmt.Printf("%b %b %b\n", FlagRed, FlagGreen, FlagBlue)
上面例子的结果是 2,4,8 (0b1,0b10,0b100)
上面例子引申出 type 定义:
go1.9 之前 type byte uint8
go1.9 之后 type byte=uint8
值得注意的是 重定义的类型必须是本地类型,import的包里面的类型不能起别名
九、数组
var team [3]string
team[0] = “hammer”
…
var team = […]string{“hammer”, “soldier”, “mum”} //!!这里的…意思是数组大小编译器自己看着办
数组遍历函数
var team [3]string
team[0] = "hammer"
team[1] = "soldier"
team[2] = "mum"
for k, v := range team {
fmt.Println(k, v)
}
遍历出的键 k 为数组的索引,值 v 为数组的每个元素值。
这个range,没有接触过的真的会被高昏头,详细的推荐 https://www.jianshu.com/p/4205659ca419 ,简单来说就是一个内嵌的遍历函数
十、切片
var highRiseBuilding [30]int
for i := 0; i < 30; i++ {
highRiseBuilding[i] = i + 1
}
// 区间
fmt.Println(highRiseBuilding[10:15])
// 中间到尾部的所有元素
fmt.Println(highRiseBuilding[20:])
// 开头到中间的所有元素
fmt.Println(highRiseBuilding[:2])
代码结果
[11 12 13 14 15]
[21 22 23 24 25 26 27 28 29 30]
[1 2]
var a = []{1,2,3}
a[:] //原始切片 {1,2,3}
a[0:0] // {}
-
make函数构造切片
make( []T, size, cap ) //可缺省size,cap
T:切片的元素类型。
size:就是为这个类型分配多少个元素。
cap:预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题。 -
append()为切片添加元素
team := []string{"Pig", "Flyingcake", "Chicken"}
car = append(car, team)
-
copy():切片复制
refData := srcData //引用
copy(copyData, srcData) //将数据复制到新的切片空间中
copy(copyData, srcData[4:6]) //复制一部分 -
切片删除
十一、map映射
scene := make(map[string]int)
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960
for k, v := range scene {
fmt.Println(k, v)
}
- make(map[keyType] valueType, cap),keyType表示键类型,valueType表示值类型
- map 不需要回收,直接make新的就可以
- sync.Map
并发访问map需要加锁,go提供了 sync.Map ,不需要写代码的人手动加锁,他自己内部维护,下面是具体实现
package main
import (
"fmt"
"sync"
)
func main() {
var scene sync.Map
// 将键值对保存到sync.Map
scene.Store("greece", 97)
scene.Store("london", 100)
scene.Store("egypt", 200)
// 从sync.Map中根据键取值
fmt.Println(scene.Load("london"))
// 根据键删除对应的键值对
scene.Delete("london")
// 遍历所有sync.Map中的键值对
scene.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
}
十二、list
在 Go 语言中,将列表使用 container/list 包来实现,内部的实现原理是双链表
l := list.New()
l.PushBack("fist")
l.PushFront(67)
l.InsertAfter("high", element)
l.InsertBefore("noon", element)
l.Remove(element) for i := l.Front(); i != nil; i = i.Next() {
fmt.Println(i.Value)
}