feat: 笔记同步

master
old-tom 2 years ago
parent 9eedfe786b
commit 893daea019

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@ -0,0 +1,2 @@
1. 小组周会
2. 学习

@ -0,0 +1,81 @@
### 一、包名
**使用小写字母:** 包名应该使用小写字母,不要使用下划线或混合大小写。
```text
// 不推荐
package my_package
// 推荐
package mypackage
```
**避免泛化的名称:** 包名应该具有明确的含义,避免使用过于泛化的名称。
```text
// 不推荐
package util
// 推荐
package fileutil
```
### 二、变量及常量
**使用驼峰命名法:** 变量和函数名使用驼峰命名法,即首个单词小写,后续单词首字母大写。
```text
// 不推荐
var my_variable int
// 推荐
var myVariable int
```
**短小而具有描述性:** 变量名应该既简短又具有描述性,避免使用单字母名称,除非是循环变量。
```text
// 不推荐
var n int
// 推荐
var itemCount int
```
**常量全大写:** 常量名应该全大写,用下划线分隔单词。
```text
// 不推荐
const Pi = 3.14
// 推荐
const PI = 3.14
```
### 三、函数及方法
**使用驼峰命名法:** 函数和方法名同样使用驼峰命名法。
```text
// 不推荐
func calculate_sum() int
// 推荐
func calculateSum() int
```
**使用动词:** 函数名应该使用动词,明确描述函数的操作。
```text
// 不推荐
func data()
// 推荐
func fetchData()
```
### 四、结构体及接口
**使用驼峰命名法:** 结构体和接口名同样应该使用驼峰命名法。
```text
// 不推荐
type employee_data struct {}
// 推荐
type EmployeeData struct {}
```
**避免缩写:** 尽量避免使用缩写,除非是广泛接受的行业标准。
```text
// 不推荐
type HTMLParser interface {}
// 推荐
type HTMLParserInterface interface {}
```
### 五、测试文件
**以 `_test.go` 结尾:** 测试文件应该以 **`_test.go`** 结尾,使其与普通源代码文件区分开。
```text
// 测试文件名
mypackage_test.go
```
**测试函数使用 `Test` 前缀:** 测试函数的命名应以 **`Test`** 为前缀,后面跟被测试的函数名。
```text
// 不推荐
func checkData() {}
// 推荐
func TestCheckData() {}
```

@ -0,0 +1,204 @@
golang 在container包下提供了list双链表、heap、ring等容器结构
![[Pasted image 20231225085517.png]]
# 一、list
golang 中实现的list为双向链表。双向链表一般用于经常堆头部和尾部进行增删的场景同时它不需要在一开始初始化它的容量它的容量随着使用动态变化扩大or缩小
核心数据结构(Element、List)
```golang
// 链表的一个元素
type Element struct {
next, prev *Element // 前后指针
list *List // 所属链表
Value any // 值
}
```
```golang
// 链表
type List struct {
root Element // 哨兵元素
len int // 链表元素个数
}
```
![[Pasted image 20231225170420.png]]
## 1.初始化
```golang
package main
import (
"container/list"
"fmt"
)
func main()
// 使用list.New()直接初始化
l1 := list.New()
l1.PushFront(1)
fmt.Println(l1.Front().Value) // 1
// 使用list.List{}延迟初始化
l2 := list.List{}
l2.PushFront(2)
fmt.Println(l2.Front().Value) // 2
}
```
## 2.常用API
+ PushFront 链表头部添加元素
+ PushBack 尾部添加元素
+ PushFrontList 链表头部插入链表
+ PushBackList 尾部插入链表
+ Front 获取头部元素
+ Back 获取尾元素
+ Len 获取长度
+ InsertBefore 某个元素前插入
+ InsertAfter 某个元素后插入
+ MoveBefore 移动元素到某个元素前面
+ MoveAfter 移动元素到某个元素后面
+ MoveToFront 移动元素到头部
+ MoveToBack 移动元素到尾部
# 二、heap
堆是一颗完全二叉树,按照比较规则不同,分为最大堆和最小堆。以最小堆为例,父节点总是比子节点小。
堆的下标公式:
parent(i)=floor((i-1)/2) 向下取整
left(i)=2i+1
right(i)=2i+2
golang 提供了最小堆算法其中包含5个接口需要开发者自行实现**作为官方包Golang 希望提供给大家一种简单的接入方式,官方提供好算法的内核,大家接入就 ok。采用的是定义一个接口开发者来实现的方式**
```golang
type Interface interface {
sort.Interface
Push(x any) // 入堆
Pop() any // 出堆
}
type Interface interface {
Len() int //堆大小
Less(i, j int) bool //比较
Swap(i, j int) //交换
}
```
## 例一:最小堆
```golang
package mycontainer
type IntHeap []int
// Push IntHeap全局共享切只有一个所以需要对类型本身进行操作所以使用指针
func (h *IntHeap) Push(x any) {
//append需要传入切片切片是引用传递所以需要*h,
*h = append(*h, x.(int))
}
// Pop
//
// @Description: 从数组移除一个元素
// @receiver h
// @return any
func (h *IntHeap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
// Len
//
// @Description: 计算元素大小
// @receiver h
// @return int
func (h IntHeap) Len() int {
return len(h)
}
// Less
//
// @Description: 比较大小
// @receiver h
// @param i
// @param j
// @return bool
func (h IntHeap) Less(i, j int) bool {
return h[i] < h[j]
}
// Swap
//
// @Description: 交换i,j下标元素
// @receiver h
// @param i
// @param j
func (h IntHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
// TestIntHeap
//
// @Description: 测试自定义堆
// @param t
func TestIntHeap(t *testing.T) {
//因为pop和push方法需要传入指针
h := &myc.IntHeap{7, 9, 10}
print(h)
//堆初始化,用于构建二叉树
heap.Init(h)
//添加元素
heap.Push(h, 3)
fmt.Printf("minimum: %d\n", (*h)[0])
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h))
}
}
```
## 例二:优先队列
```golang
type Item struct {
value string
priority int
index int
}
type PriorityQueue []*Item
func (p *PriorityQueue) Push(x any) {
n := len(*p)
item := x.(*Item)
item.index = n
*p = append(*p, item)
}
func (p *PriorityQueue) Pop() any {
old := *p
n := len(old)
item := old[n-1]
item.index = -1
*p = old[0 : n-1]
return item
}
func (p PriorityQueue) Len() int {
return len(p)
}
func (p PriorityQueue) Less(i, j int) bool {
return p[i].priority > p[j].priority
}
func (p PriorityQueue) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
p[i].index = i
p[j].index = j
}
// 更新元素优先级
func (p *PriorityQueue) update(item *Item, value string, priority int) {
item.value = value
item.priority = priority
//二叉堆重排序
heap.Fix(p, item.index)
}
```
# 三、ring

@ -0,0 +1,76 @@
golang 中默认是值传递和java有所区别需要注意。
在 C 语言中,数组变量是指向第一个元素的指针,但是 Go 语言中并不是。Go 语言中,数组变量属于值类型(value type),因此当一个数组变量被赋值或者传递时,实际上会复制整个数组。
为了避免复制数组,一般会传递指向数组的指针。例如:
```golang
func square(arr *[3]int) {
for i, num := range *arr {
(*arr)[i] = num * num
}
}
func TestArrayPointer(t *testing.T) {
a := [...]int{1, 2, 3}
square(&a)
fmt.Println(a) // [1 4 9]
if a[1] != 4 && a[2] != 9 {
t.Fatal("failed")
}
}
```
## 值接收者与指针接收者
某个类型定义的方法其接收者既有值类型又有指针类型。例如自定义heap实现
```golang
type IntHeap []int
// Push IntHeap全局共享切只有一个所以需要对类型本身进行操作所以使用指针
func (h *IntHeap) Push(x any) {
//append需要传入切片切片是引用传递所以需要*h,
*h = append(*h, x.(int))
}
// Pop
//
// @Description: 从数组移除一个元素
// @receiver h
// @return any
func (h *IntHeap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
// Len
//
// @Description: 计算元素大小
// @receiver h
// @return int
func (h IntHeap) Len() int {
return len(h)
}
// Less
//
// @Description: 比较大小
// @receiver h
// @param i
// @param j
// @return bool
func (h IntHeap) Less(i, j int) bool {
return h[i] < h[j]
}
// Swap
//
// @Description: 交换i,j下标元素
// @receiver h
// @param i
// @param j
func (h IntHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
```
其中Push和Pop方法是指针接收其他方法是值接收。其中Push和Pop方法需要设置对象本身例如代码中的数组因此必须使用指针避免复制。Swap方法较为特殊golang默认会交换指针。
Loading…
Cancel
Save