1. go mod tidy 自动下载所有依赖
2. 安装ptotobuf
https://github.com/protocolbuffers/protobuf/releases
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
//protoc -I . helloworld.proto --go_out=plugins=grpc:.
//protoc --go_out=. helloworld.proto
protoc --go-grpc_out=. helloworld.proto
3.slice、map、chan
Golang 默认都是采用值传递,有些值天生就是指针:slice、map、channel。声明后还需要初始化make分配内存
3.1 :=不能声明全局变量//推导变量类型不支持全局变量声明
3.2 iota 仅可以和 const一起使用来定义有规则的枚举
3.3 defer 延迟处理并压栈(在return之后执行,先入后出,后入先出)
3.4 slice(动态数组),动态数组引用传值,且形参一致
slice4种声明方式
myslice1 := []int{1,2,3}
var myslice2 []int
myslice2 = make([]int, 3)
var myslice3 []int = make([]int, 3)
myslice4 := make([]int, 3)
注意:定长数组是值传递,slice 是指针传递,slice切片是左闭右开。
map3种声明方式
var myMap1 map[string]string
myMap1 = make(map[string]string, 10)
myMap1["one"] = "aaa"
myMap2 := make(map[int]string)
myMap2[1] = "aaa"
myMap3 := make(map[string]string) {
"one": "aaa",
"two": "bbb",
}
4.chan的声明和使用
ch1 := make(chan Type) //等价于make(chan Type, 0)
ch2 := make(chan Type, capacity)
channel <- value //发送value到channel
<-channel //接收并将其丢弃
x := <-channel //从channel中接收数据,并赋值给x
x, ok := <-channel //同上,同时检查通道是否已关闭或为空
报错package xxx is not in GOROOT or GOPATH
解决:初始化一个go.mod,...\Go\GolangStudy\5-init> go mod init 5-init,然后使用时import "5-init"即可
5. 结构的声明和实例化
// 类声明
type Person struct {
Name string
Age int
Doc []string // slice切片
}
// 类方法声明-传递值对象
func (p *Person) P1() {
p.Name = "Tinywan"
p.Age = 24
}
// 类方法声明-传递指针对象
func (p *Person) P2() {
p.Name = "Tinyaiai"
p.Age = 22
}
func main() {
// 实例化对象 实例化的时候可以初始化属性值,如果没有指明则默认为系统默认值
p1 := &Person{}
p1.Name = "ShaoBo Wan"
p1.Age = 20
p2 := &Person{Name:"HaHa"}
p3 := new(Person)
p3.Name = "New Name"
p4 := Person{}
p4.Name = "Name 001"
p4.Age = 26
p5 := Person{Name:"Name 002",Age:28}
// 使用中如果包含数组(动态数组 slice切片),结构体的实例化需要加上类型如上如果intro的类型是[]string
p6 := &Person{
"zhangsan",
25,
[]string{"lisi", "wangwu"},
}
fmt.Println(p1, "\n", p2, "\n", p3, "\n", p4, "\n", p5, "\n", p6, "\n")
//&{ShaoBo Wan 20 []} &{HaHa 0 []} &{New Name 0 []} {Name 001 26 []} {Name 002 28 []} &{zhangsan 25 [lisi wangwu]}
fmt.Println(&p1, "\n", &p2, "\n", &p3, "\n", &p4, "\n", &p5, "\n", &p6, "\n")
//0xc000006028 0xc000006030 0xc000006038 &{Name 001 26 []} &{Name 002 28 []} 0xc000006040
fmt.Println(*p1, "\n", *p2, "\n", *p3, "\n", *p6, "\n")
}
小结:
1、使用中如果包含数组,结构体的实例化需要加上类型如上如果Doc的类型是[]string。
2、实例化的时候可以初始化属性值,如果没有指明则默认为系统默认值。
3、加&符号和new的是指针对象,没有的则是值对象,这点和php、java不一致,在传递对象的时候要根据实际情况来决定是要传递指针还是值。
4、当对象比较小的时候传递指针并不划算。
6. Go常用算法
数据结构和算法(Golang实现)https://www.cnblogs.com/nima/p/12711150.html(https://goa.lenggirl.com/#/basic/before)
数据结构主要用来组织数据,也作为数据的容器,载体。各种各样的算法,都需要使用一定的数据结构来组织数据。
6.1 常见的典型数据结构有:链表,栈和队列,树,图
上述可以延伸出各种各样的术语和结构,如列表,集合,哈希表,堆,优先队列,二叉树,红黑树,B+树以及各种变种等。
6.2 算法目的就是为了解决问题,基本的算法分类有:排序算法,查找算法,图相关的算法,其他的算法
7.Go并发示例
交替打印数字和字母
问题描述:
使用两个 goroutine 交替打印序列,一个 goroutine 打印数字, 另外一个 goroutine 打印字母,
最终效果如下:12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728
解题思路:问题很简单,使用 channel 来控制打印的进度。使用两个 channel ,来分别控制数字和字母的打印序列, 数字打印完成后通过 channel 通知字母打印,
字母打印完成后通知数字打印,然后周而复始的工作。
源码参考
letter,number := make(chan bool),make(chan bool)
wait := sync.WaitGroup{}
go func() {
i := 1
for {
select {
case <-number:
fmt.Print(i)
i++
fmt.Print(i)
i++
letter <- true
}
}
}()
wait.Add(1)
go func(wait *sync.WaitGroup) {
i := 'A'
for{
select {
case <-letter:
if i >= 'Z' {
wait.Done()
return
}
fmt.Print(string(i))
i++
fmt.Print(string(i))
i++
number <- true
}
}
}(&wait)
number<-true
wait.Wait()
源码解析:
这里用到了两个channel负责通知,letter负责通知打印字母的goroutine来打印字母,number用来通知打印数字的goroutine打印数字。
wait用来等待字母打印完成后退出循环。
8. https://www.jianshu.com/p/c118d2de698e---使用golang的sort包进行排序
sort.Sort(OneList(oneArr))
Len() 函数 返回要排序的序列的长度
Less() 函数 返回排序需要的比较的规则,如果符合这个规则,就进行交换
Swap() 函数 进行排序的交换规则