├── performance_al └── perf_test.go ├── nfa ├── nfa_test.go └── nfa_leetcode.go ├── trie ├── trie_test.go └── trie.go ├── quicksort ├── quiksort_test.go ├── quicksort.go └── quicksort_leetcode.go ├── go.mod ├── heap ├── heap_test.go └── heap.go ├── .bash_history ├── bitmap ├── bitmap_test.go └── bitmap.go ├── lru ├── lru_test.go └── lru.go ├── bloomfilter ├── bloomfilter_test.go └── bloomfilter.go ├── httpsdemo ├── server │ └── main.go └── client │ └── main.go ├── binarysearch ├── binarysearch.go ├── leetcode35.go └── leetcode33.go ├── layer4balance ├── docker-compose.yaml └── proxy │ └── proxy_server.go ├── mmapdemo └── main.go ├── go.sum ├── balancepolicy └── policy.go ├── mergesort ├── main.go └── mergesort_leetcode.go ├── gopool └── main.go ├── consistenthash └── consistenthash.go ├── ReadMe.md └── skiplist └── skiplitst.go /performance_al/perf_test.go: -------------------------------------------------------------------------------- 1 | package performance_al 2 | 3 | import "testing" 4 | 5 | // 测试各种时间复杂度的算法性能 6 | func TestPerformance(t *testing.T) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /nfa/nfa_test.go: -------------------------------------------------------------------------------- 1 | package nfa 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNFA_Match(t *testing.T) { 9 | nfa := New("a*") 10 | fmt.Println(nfa.Match("aa")) 11 | } 12 | -------------------------------------------------------------------------------- /trie/trie_test.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | tree := New() 10 | tree.Add("hello") 11 | fmt.Println(tree.Exits("hellw")) 12 | } 13 | -------------------------------------------------------------------------------- /quicksort/quiksort_test.go: -------------------------------------------------------------------------------- 1 | package quicksort 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestFindKthLargest(t *testing.T) { 9 | fmt.Println(findKthLargest([]int{7, 6, 5, 4, 3, 2, 1}, 2)) 10 | } 11 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module codelearning 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 7 | github.com/spaolacci/murmur3 v1.1.0 8 | ) 9 | 10 | require ( 11 | github.com/kr/pretty v0.1.0 // indirect 12 | github.com/kr/text v0.1.0 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /heap/heap_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestHeapify(t *testing.T) { 9 | arr := []int{10, 100, 90, 1, 4, 20, 8} 10 | h := HeapInsert(arr) 11 | fmt.Println(h.arr) 12 | for i := 0; i < len(arr); i++ { 13 | fmt.Println(h.Pop()) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.bash_history: -------------------------------------------------------------------------------- 1 | ls 2 | cd root/ 3 | ls 4 | cd layer4balance/ 5 | ls 6 | ls 7 | ./main.go 8 | ./layer4balance 9 | exit 10 | cd root/ 11 | cd layer4balance/ 12 | ls 13 | ping 192.168.17.150 14 | ./layer4balance 15 | exit 16 | cd root/ 17 | cd layer4balance/ 18 | ./layer4balance 19 | exit 20 | cd root/layer4balance/ 21 | ./layer4balance 22 | exit 23 | -------------------------------------------------------------------------------- /bitmap/bitmap_test.go: -------------------------------------------------------------------------------- 1 | package bitmap 2 | 3 | import ( 4 | "github.com/bmizerany/assert" 5 | "testing" 6 | ) 7 | 8 | func TestBitmap(t *testing.T) { 9 | bm := New(10) 10 | bm.Set(9) 11 | bm.Set(10) 12 | bm.Set(1) 13 | assert.Equal(t, bm.Exits(9), true) 14 | assert.Equal(t, bm.Exits(10), true) 15 | assert.Equal(t, bm.Exits(1), true) 16 | bm.Clean(9) 17 | assert.Equal(t, bm.Exits(9), false) 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lru/lru_test.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestLRU_Add(t *testing.T) { 9 | cache := New(4) 10 | cache.Add(3) 11 | fmt.Println("0", cache) 12 | cache.Add(4) 13 | fmt.Println("1", cache) 14 | cache.Add(4) 15 | fmt.Println("2", cache) 16 | cache.Add(6) 17 | cache.Add(7) 18 | fmt.Println("3", cache) 19 | cache.Add(8) 20 | fmt.Println("4", cache) 21 | 22 | } 23 | -------------------------------------------------------------------------------- /bloomfilter/bloomfilter_test.go: -------------------------------------------------------------------------------- 1 | package bloomfilter 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "testing" 7 | ) 8 | 9 | func TestBloomFilter_Add(t *testing.T) { 10 | bf := New(10, 3) 11 | bf.Add("test2") 12 | fmt.Println(bf.MightContain("test2")) 13 | } 14 | 15 | func TestNew(t *testing.T) { 16 | var maxuint uint64 = math.MaxUint64 17 | fmt.Println(maxuint) 18 | fmt.Println(int64(maxuint)) 19 | fmt.Println(uint64ToInt64(maxuint) & math.MaxInt64) 20 | } 21 | -------------------------------------------------------------------------------- /httpsdemo/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | func main() { 10 | 11 | s := &http.Server{ 12 | Addr: ":443", 13 | Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 14 | fmt.Fprintf(w, "Hello, World!\n") 15 | }), 16 | TLSConfig: &tls.Config{ 17 | ClientAuth: tls.RequireAndVerifyClientCert, 18 | }, 19 | } 20 | 21 | fmt.Println(s.ListenAndServeTLS("./final_csr.crt", 22 | "./final_private.key")) 23 | } 24 | -------------------------------------------------------------------------------- /binarysearch/binarysearch.go: -------------------------------------------------------------------------------- 1 | package binarysearch 2 | 3 | func Search(arr []int, num int) int { 4 | return searchHelper(arr, 0, len(arr)-1, num) 5 | } 6 | 7 | // 在[l..r]中寻找num 8 | func searchHelper(arr []int, l, r int, num int) int { 9 | // 定义终止条件 10 | if l > r { 11 | return -1 12 | } 13 | mid := (r - l) / 2 14 | if arr[mid] == num { 15 | return mid 16 | } 17 | if arr[mid] > num { 18 | // 左半部分寻找 19 | return searchHelper(arr, l, mid-1, num) 20 | } 21 | // arr[mid] < num 右半部分寻找 22 | return searchHelper(arr, mid+1, r, num) 23 | } 24 | -------------------------------------------------------------------------------- /layer4balance/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | mysql1: 4 | restart: always 5 | image: amd64/mysql:latest 6 | container_name: mysql1 7 | environment: 8 | - "MYSQL_ROOT_PASSWORD=1234567" 9 | - "MYSQL_DATABASE=test" 10 | ports: 11 | - "3306:3306" 12 | 13 | mysql2: 14 | restart: always 15 | image: amd64/mysql:latest 16 | container_name: mysql2 17 | environment: 18 | - "MYSQL_ROOT_PASSWORD=1234567" 19 | - "MYSQL_DATABASE=test2" 20 | ports: 21 | - "3307:3306" -------------------------------------------------------------------------------- /binarysearch/leetcode35.go: -------------------------------------------------------------------------------- 1 | package binarysearch 2 | 3 | func searchInsert(nums []int, target int) int { 4 | return searchInsertHelper(nums, 0, len(nums)-1, target) 5 | } 6 | 7 | // 在[l...r] 中寻找元素插入的索引值,即找到数组中第一个大于等于该值的索引位置 8 | func searchInsertHelper(arr []int, l, r int, num int) int { 9 | // 定义终止条件 10 | if l > r { 11 | return l 12 | } 13 | mid := (r - l) / 2 14 | if arr[mid] == num { 15 | return mid 16 | } 17 | if arr[mid] >= num { 18 | // 左半部分寻找 19 | return searchHelper(arr, l, mid-1, num) 20 | } 21 | // arr[mid] < num 右半部分寻找 22 | return searchHelper(arr, mid+1, r, num) 23 | } 24 | -------------------------------------------------------------------------------- /mmapdemo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | "syscall" 7 | ) 8 | 9 | func main() { 10 | 11 | http.HandleFunc("/tradition", func(writer http.ResponseWriter, request *http.Request) { 12 | 13 | f, _ := os.Open("./testmmap.txt") 14 | buf := make([]byte, 1024) 15 | n, _ := f.Read(buf) 16 | writer.Write(buf[:n]) 17 | }) 18 | 19 | http.HandleFunc("/mmap", func(writer http.ResponseWriter, request *http.Request) { 20 | f, _ := os.Open("./testmmap.txt") 21 | data, err := syscall.Mmap(int(f.Fd()), 0, 5, syscall.PROT_READ, syscall.MAP_SHARED) 22 | if err != nil { 23 | panic(err) 24 | } 25 | writer.Write(data) 26 | }) 27 | http.ListenAndServe(":8080", http.DefaultServeMux) 28 | } 29 | -------------------------------------------------------------------------------- /httpsdemo/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | ) 9 | 10 | func main() { 11 | 12 | cliCrt, err := tls.LoadX509KeyPair("./client_csr.crt", "./client_private.key") 13 | if err != nil { 14 | fmt.Println("Loadx509keypair err:", err) 15 | return 16 | } 17 | tr := &http.Transport{ 18 | TLSClientConfig: &tls.Config{ 19 | Certificates: []tls.Certificate{cliCrt}, 20 | }, 21 | } 22 | client := &http.Client{Transport: tr} 23 | resp, err := client.Get("https://www.lanpangzi.com") 24 | if err != nil { 25 | fmt.Println("Get error:", err) 26 | return 27 | } 28 | defer resp.Body.Close() 29 | body, err := ioutil.ReadAll(resp.Body) 30 | fmt.Println(string(body)) 31 | } 32 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= 2 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 3 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 4 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 5 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 6 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 7 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 8 | github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 9 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 10 | -------------------------------------------------------------------------------- /trie/trie.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | type Node struct { 4 | IsEnd bool 5 | Children map[rune]*Node 6 | } 7 | 8 | type Trie struct { 9 | root *Node 10 | } 11 | 12 | func New() *Trie { 13 | return &Trie{ 14 | root: &Node{ 15 | IsEnd: false, 16 | Children: make(map[rune]*Node), 17 | }} 18 | } 19 | 20 | func (t *Trie) Add(words string) { 21 | node := t.root 22 | for _, ch := range words { 23 | child, ok := node.Children[ch] 24 | if !ok { 25 | child = &Node{IsEnd: false, Children: make(map[rune]*Node)} 26 | node.Children[ch] = child 27 | } 28 | node = child 29 | } 30 | node.IsEnd = true 31 | } 32 | 33 | func (t *Trie) Exits(words string) bool { 34 | node := t.root 35 | for _, ch := range words { 36 | child, ok := node.Children[ch] 37 | if !ok { 38 | return false 39 | } 40 | node = child 41 | } 42 | return true 43 | } 44 | -------------------------------------------------------------------------------- /binarysearch/leetcode33.go: -------------------------------------------------------------------------------- 1 | package binarysearch 2 | 3 | func search(nums []int, target int) int { 4 | return searchhelper(nums, 0, len(nums)-1, target) 5 | } 6 | 7 | // 查找[start,end] 范围内有没有target的值 8 | // 例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 9 | func searchhelper(nums []int, start int, end int, target int) int { 10 | if start > end { 11 | return -1 12 | } 13 | mid := (end-start)/2 + start 14 | if nums[mid] == target { 15 | return mid 16 | } 17 | // 左边数组, target 如果在start end范围内,正常二分 18 | if nums[mid] >= nums[0] { 19 | if nums[mid] > target && target >= nums[start] { 20 | return searchhelper(nums, start, mid-1, target) 21 | } 22 | return searchhelper(nums, mid+1, end, target) 23 | } 24 | // 右边数组 25 | if nums[mid] < target && target <= nums[end] { 26 | return searchhelper(nums, mid+1, end, target) 27 | } 28 | return searchhelper(nums, start, mid-1, target) 29 | } 30 | -------------------------------------------------------------------------------- /balancepolicy/policy.go: -------------------------------------------------------------------------------- 1 | package balancepolicy 2 | 3 | import "sync" 4 | 5 | type Policy interface { 6 | AddNode(addr string, nodeName string) 7 | PickNode(key string) string 8 | } 9 | 10 | type RoundRobin struct { 11 | lock sync.Mutex 12 | index int64 13 | nodeInfo map[string]string 14 | nodes []string 15 | } 16 | 17 | func NewRoundRobin() *RoundRobin { 18 | return &RoundRobin{ 19 | index: 0, 20 | nodeInfo: map[string]string{}, 21 | nodes: make([]string, 0), 22 | } 23 | } 24 | 25 | func (r *RoundRobin) AddNode(addr string, nodeName string) { 26 | r.nodeInfo[nodeName] = addr 27 | r.nodes = append(r.nodes, nodeName) 28 | } 29 | 30 | func (r *RoundRobin) PickNode(key string) string { 31 | r.lock.Lock() 32 | defer r.lock.Unlock() 33 | num := r.index % int64(len(r.nodes)) 34 | r.index++ 35 | if r.index < 0 { 36 | // 防止溢出 37 | r.index = 0 38 | } 39 | return r.nodeInfo[r.nodes[num]] 40 | } 41 | -------------------------------------------------------------------------------- /bitmap/bitmap.go: -------------------------------------------------------------------------------- 1 | package bitmap 2 | 3 | type BitMap struct { 4 | flags []byte 5 | } 6 | 7 | func New(max int64) *BitMap { 8 | flagLen := max/8 + 1 9 | return &BitMap{flags: make([]byte, flagLen)} 10 | } 11 | 12 | // 关键是计算index 在位图上的位置 13 | 14 | func (b *BitMap) Set(index int64) { 15 | arrIndex := index / 8 16 | offset := index % 8 17 | // 将offset位置设置为1,或运算,0 | 1 = 1 1|1= 1, 0|0 =0, 1的| 将原值设置为1 ,0的| 不改变原值 18 | b.flags[arrIndex] = b.flags[arrIndex] | (0x1 << offset) 19 | } 20 | 21 | func (b *BitMap) Clean(index int64) { 22 | arrIndex := index / 8 23 | offset := index % 8 24 | // 0 & 1 = 0 ,0 & 0 = 0, 1&1 =1 1的& 不会改变原来的值, 0的& 将原值变为0 25 | b.flags[arrIndex] = b.flags[arrIndex] & ^(0x1 << offset) 26 | } 27 | 28 | func (b *BitMap) Exits(index int64) bool { 29 | arrIndex := index / 8 30 | offset := index % 8 31 | res := b.flags[arrIndex] & (0x1 << offset) 32 | if res == 0 { 33 | return false 34 | } 35 | return true 36 | } 37 | -------------------------------------------------------------------------------- /mergesort/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | sortArray([]int{5, 2, 3, 1}) 5 | } 6 | 7 | func sortArray(nums []int) []int { 8 | mergesort(nums, 0, len(nums)-1) 9 | return nums 10 | } 11 | 12 | // 将数组[l...r]一分为二,分别对左右数组进行排序,然后对排序好的数组进行归并 13 | func mergesort(arr []int, l, r int) { 14 | if l >= r { 15 | return 16 | } 17 | mid := (l + r) / 2 18 | mergesort(arr, l, mid) 19 | mergesort(arr, mid+1, r) 20 | merge(arr, l, mid, r) 21 | } 22 | 23 | // [l...mid] [mid+1...r] 24 | func merge(arr []int, l, mid, r int) { 25 | arr1 := arr[l : mid+1] 26 | arr2 := arr[mid+1 : r+1] 27 | newArr := make([]int, r-l+1) 28 | i := 0 // 当前遍历元素 29 | j := 0 30 | k := 0 31 | for i < len(arr1) && j < len(arr2) { 32 | if arr1[i] > arr2[j] { 33 | newArr[k] = arr2[j] 34 | j++ 35 | k++ 36 | continue 37 | } 38 | newArr[k] = arr1[i] 39 | k++ 40 | i++ 41 | } 42 | if i == len(arr1) { 43 | copy(newArr[k:], arr2[j:]) 44 | } 45 | if j == len(arr2) { 46 | copy(newArr[k:], arr1[i:]) 47 | } 48 | copy(arr[l:], newArr) 49 | } 50 | -------------------------------------------------------------------------------- /gopool/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // 实现一个协程池,设计一个只能有那么多个协程在运行 9 | 10 | type pool struct { 11 | tasks chan func() 12 | idleTime time.Duration 13 | } 14 | 15 | func (p *pool) Submit(f func()) { 16 | p.tasks <- f 17 | } 18 | 19 | func NewPool(num int) *pool { 20 | p := &pool{ 21 | tasks: make(chan func(), num), 22 | idleTime: time.Second * 10, 23 | } 24 | p.start() 25 | return p 26 | } 27 | 28 | func (p *pool) start() { 29 | go func() { 30 | for task := range p.tasks { 31 | go func() { 32 | task() 33 | for { 34 | select { 35 | case task := <-p.tasks: 36 | fmt.Println("沿用协程") 37 | task() 38 | case <-time.After(p.idleTime): 39 | fmt.Println("协程销毁") 40 | return 41 | } 42 | } 43 | }() 44 | } 45 | }() 46 | } 47 | 48 | func main() { 49 | po := NewPool(1) 50 | po.Submit(func() { 51 | fmt.Println("执行了") 52 | time.Sleep(time.Second) 53 | }) 54 | for i := 0; i < 1000; i++ { 55 | po.Submit(func() { 56 | fmt.Println("执行了", i) 57 | }) 58 | } 59 | 60 | time.Sleep(time.Hour) 61 | } 62 | -------------------------------------------------------------------------------- /quicksort/quicksort.go: -------------------------------------------------------------------------------- 1 | package quicksort 2 | 3 | import ( 4 | "math/rand" 5 | ) 6 | 7 | func sortArray(nums []int) []int { 8 | quickSort(nums, 0, len(nums)-1) 9 | return nums 10 | } 11 | 12 | func swap(arr []int, i, j int) { 13 | tmp := arr[i] 14 | arr[i] = arr[j] 15 | arr[j] = tmp 16 | } 17 | 18 | /** 19 | 选定基点v, 让基点左边部分 < v 右边部分 > v , 中间部分等于v 20 | [l+1...lt] < v 21 | [gt...r] > v 22 | i 代表当前需要遍历的元素 23 | 24 | 快排每次分区排序后,能够让基点在数组中正确的位置上 25 | */ 26 | 27 | // 对[l..r]快排 28 | func quickSort(arr []int, l int, r int) { 29 | if l >= r { 30 | return 31 | } 32 | lt := l // 小于v的右边界 33 | gt := r + 1 // 大于v的左边界 34 | i := l + 1 // 当前遍历的元素 35 | swap(arr, l, rand.Int()%(r-l+1)+l) 36 | v := arr[l] 37 | for i < gt { 38 | if v > arr[i] { 39 | tmp := arr[lt+1] 40 | arr[lt+1] = arr[i] 41 | arr[i] = tmp 42 | lt++ 43 | i++ 44 | continue 45 | } 46 | if v < arr[i] { 47 | gt-- 48 | tmp := arr[gt] 49 | arr[gt] = arr[i] 50 | arr[i] = tmp 51 | continue 52 | } 53 | i++ 54 | } 55 | tmp := arr[lt] 56 | arr[lt] = v 57 | arr[l] = tmp 58 | lt-- 59 | quickSort(arr, l, lt) 60 | quickSort(arr, gt, r) 61 | } 62 | -------------------------------------------------------------------------------- /layer4balance/proxy/proxy_server.go: -------------------------------------------------------------------------------- 1 | package proxy 2 | 3 | import ( 4 | "codelearning/balancepolicy" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | ) 10 | 11 | type Server struct { 12 | Li net.Listener 13 | Balance balancepolicy.Policy 14 | } 15 | 16 | func (s *Server) Run() { 17 | for { 18 | c, err := s.Li.Accept() 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | go func(c net.Conn) { 23 | remoteAddr := c.RemoteAddr() 24 | backendIp := s.Balance.PickNode(remoteAddr.String()) 25 | serverConn, err := net.Dial("tcp", backendIp) 26 | if err != nil { 27 | log.Fatal(err) 28 | c.Close() 29 | return 30 | } 31 | fmt.Println("获取到了新连接", remoteAddr, backendIp) 32 | go func() { 33 | _, err := io.Copy(serverConn, c) 34 | if err != nil { 35 | fmt.Println(err, 1) 36 | } 37 | c.Close() 38 | serverConn.Close() 39 | fmt.Println("结束1", err) 40 | }() 41 | go func() { 42 | _, err := io.Copy(c, serverConn) 43 | if err != nil { 44 | fmt.Println(err, 2) 45 | } 46 | c.Close() 47 | serverConn.Close() 48 | fmt.Println("结束2", err) 49 | }() 50 | }(c) 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /consistenthash/consistenthash.go: -------------------------------------------------------------------------------- 1 | package consistenthash 2 | 3 | import ( 4 | "fmt" 5 | "hash/crc32" 6 | "sort" 7 | ) 8 | 9 | type ConsistentHash struct { 10 | nodes map[uint32]string 11 | keys []uint32 12 | replicates int 13 | } 14 | 15 | func New(replicate int) *ConsistentHash { 16 | return &ConsistentHash{ 17 | nodes: make(map[uint32]string), 18 | keys: make([]uint32, 0), 19 | replicates: replicate, 20 | } 21 | } 22 | 23 | func (c *ConsistentHash) AddNodes(node string) { 24 | for i := 0; i <= c.replicates; i++ { 25 | nodename := fmt.Sprintf("%s#%d", node, i) 26 | hashKey := crc32.ChecksumIEEE([]byte(nodename)) 27 | c.nodes[hashKey] = nodename 28 | c.keys = append(c.keys, hashKey) 29 | } 30 | sort.Slice(c.keys, func(i, j int) bool { 31 | return c.keys[i] < c.keys[j] 32 | }) 33 | } 34 | 35 | func (c *ConsistentHash) GetNode(key string) string { 36 | hashKey := crc32.ChecksumIEEE([]byte(key)) 37 | nodekeyIndex := sort.Search(len(c.keys), func(i int) bool { 38 | return c.keys[i] >= hashKey 39 | }) 40 | if nodekeyIndex == len(c.keys) { 41 | nodekeyIndex = 0 42 | } 43 | return c.nodes[c.keys[nodekeyIndex]] 44 | } 45 | -------------------------------------------------------------------------------- /quicksort/quicksort_leetcode.go: -------------------------------------------------------------------------------- 1 | package quicksort 2 | 3 | /* 4 | * 5 | 6 | 215. 数组中的第K个最大元素 7 | 中等 8 | 2.3K 9 | 相关企业 10 | 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 11 | 12 | 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 13 | 14 | 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 15 | 16 | 示例 1: 17 | 18 | 输入: [3,2,1,5,6,4], k = 2 19 | 输出: 5 20 | 示例 2: 21 | 22 | 输入: [3,2,3,1,2,4,5,5,6], k = 4 23 | 输出: 4 24 | 25 | 提示: 26 | 27 | 1 <= k <= nums.length <= 105 28 | -104 <= nums[i] <= 104 29 | */ 30 | func findKthLargest(nums []int, k int) int { 31 | return partition(nums, k, 0, len(nums)-1) 32 | } 33 | 34 | // 大于 v 小于v 35 | // v [l+1..lt] [gt...r] 进行分区,判断 分区后的lt+1 和k的大小 36 | func partition(nums []int, k int, l, r int) int { 37 | lt := l 38 | v := nums[l] 39 | gt := r + 1 40 | i := l + 1 // 当前遍历元素 41 | for i < gt { 42 | if nums[i] < v { 43 | gt-- 44 | swap(nums, gt, i) 45 | continue 46 | } 47 | if nums[i] > v { 48 | lt++ 49 | swap(nums, i, lt) 50 | i++ 51 | continue 52 | } 53 | i++ 54 | } 55 | swap(nums, l, lt) 56 | lt-- 57 | // lt+ 1的元素处于正确位置lt+1 58 | if lt+1 == k-1 { 59 | return nums[lt+1] 60 | } 61 | if lt+1 < k-1 { 62 | if gt > k-1 { 63 | return nums[k-1] 64 | } 65 | return partition(nums, k, gt, r) 66 | } 67 | return partition(nums, k, l, lt) 68 | } 69 | -------------------------------------------------------------------------------- /mergesort/mergesort_leetcode.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | 剑指 Offer 51. 数组中的逆序对 5 | 困难 6 | 1.1K 7 | 相关企业 8 | 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 9 | 10 | 示例 1: 11 | 12 | 输入: [7,5,6,4] 13 | 输出: 5 14 | 15 | 限制: 16 | 17 | 0 <= 数组长度 <= 50000 18 | */ 19 | 20 | func reversePairs(nums []int) int { 21 | var cnt = 0 22 | mergesort_copy(nums, 0, len(nums)-1, &cnt) 23 | return cnt 24 | } 25 | 26 | // 将数组[l...r]一分为二,分别对左右数组进行排序,然后对排序好的数组进行归并 27 | func mergesort_copy(arr []int, l, r int, cnt *int) { 28 | if l >= r { 29 | return 30 | } 31 | mid := (l + r) / 2 32 | mergesort_copy(arr, l, mid, cnt) 33 | mergesort_copy(arr, mid+1, r, cnt) 34 | mergeCopy(arr, l, mid, r, cnt) 35 | } 36 | 37 | // [l...mid] [mid+1...r] 38 | 39 | func mergeCopy(arr []int, l, mid, r int, cnt *int) { 40 | arr1 := arr[l : mid+1] 41 | arr2 := arr[mid+1 : r+1] 42 | newArr := make([]int, r-l+1) 43 | i := 0 // 当前遍历元素 44 | j := 0 45 | k := 0 46 | for i < len(arr1) && j < len(arr2) { 47 | if arr1[i] > arr2[j] { 48 | newArr[k] = arr2[j] 49 | *cnt += len(arr1) - i 50 | j++ 51 | k++ 52 | continue 53 | } 54 | newArr[k] = arr1[i] 55 | k++ 56 | i++ 57 | } 58 | if i == len(arr1) { 59 | copy(newArr[k:], arr2[j:]) 60 | } 61 | if j == len(arr2) { 62 | copy(newArr[k:], arr1[i:]) 63 | } 64 | copy(arr[l:], newArr) 65 | } 66 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 专栏简介 4 | 5 | 大家好,我是蓝胖子,这个专栏准备拿来作为平时学习积累练习的代码。 6 | 某些代码配套有笔记和视频。我将会在下面列举出来相关链接,后面也会持续更新。 7 | 8 | #### 一致性hash原理以及实践 9 | 代码目录: [consistenthash](consistenthash) 文章笔记讲解: [一致性hash](https://mp.weixin.qq.com/s?__biz=MzU3NjY5MjY2Ng==&mid=2247487101&idx=1&sn=f4841ebdca5d59f2c8a57dbcdbb20b35&chksm=fd1146a8ca66cfbeebaa453a624fb8488922018ba5b4dd9e5a7ecab1064403b199ff1cf17cbb#rd) 10 | 11 | #### https原理 12 | 代码目录: [httpsdemo](httpsdemo) 文章笔记讲解: [https原理](https://mp.weixin.qq.com/s?__biz=MzU3NjY5MjY2Ng==&mid=2247487154&idx=1&sn=5218d88df26b092e07d593ec80ab0385&chksm=fd114667ca66cf71e687ff832948699022ab5482287cdcc601c6867935f78fcde64c01434e27#rd) 13 | 14 | 15 | 16 | #### 零拷贝原理 17 | 代码目录: [mmapdemo](mmapdemo) 文章笔记讲解: [零拷贝原理](https://mp.weixin.qq.com/s?__biz=MzU3NjY5MjY2Ng==&mid=2247487127&idx=1&sn=d21aaf1181054fca7c8c7c999c5a5041&chksm=fd114642ca66cf548c940ec73aad02380c1c06ed789b96101aa250608d113686dadea7d237b5#rd) 18 | 19 | #### golang实现四层负载均衡 20 | 代码目录: [四层负载均衡](layer4balance) 文章笔记:[golang实现四层负载均衡](https://mp.weixin.qq.com/s?__biz=MzU3NjY5MjY2Ng==&mid=2247487169&idx=1&sn=d0766ee38047acdd380c3c43d1797b54&chksm=fd114614ca66cf025387578173f618c0d7d23e6db883d71dd5b25aad0758863f73c2c375926a#rd) 21 | 22 | 23 | ## 公众号 24 | 25 | ![WechatIMG143.jpeg](https://s2.loli.net/2023/04/12/QzqyFU6tjAxKame.jpg) 26 | 27 | 28 | ## 提问与纠错 29 | 如果有疑问或者发现错误,可以在相应的 Issues 进行提问或勘误。 30 | 31 | -------------------------------------------------------------------------------- /lru/lru.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | import "strconv" 4 | 5 | type Node struct { 6 | pre, next *Node 7 | val int 8 | } 9 | 10 | type LRU struct { 11 | m map[int]*Node 12 | Root *Node 13 | maxsize int 14 | } 15 | 16 | func New(size int) *LRU { 17 | return &LRU{ 18 | m: map[int]*Node{}, 19 | Root: &Node{ 20 | pre: nil, 21 | next: nil, 22 | val: -1, 23 | }, 24 | maxsize: size, 25 | } 26 | } 27 | 28 | func (l *LRU) Add(val int) { 29 | node, ok := l.m[val] 30 | if ok { 31 | // 插入表头 32 | node.pre.next = node.next 33 | node.next = l.Root.next 34 | node.pre = l.Root 35 | if l.Root.next != nil { 36 | l.Root.next.pre = node 37 | } 38 | l.Root.next = node 39 | l.m[val] = node 40 | } else { 41 | // 生成新节点 42 | node = &Node{ 43 | pre: l.Root, 44 | next: l.Root.next, 45 | val: val, 46 | } 47 | if l.Root.next != nil { 48 | l.Root.next.pre = node 49 | } 50 | l.Root.next = node 51 | l.m[val] = node 52 | } 53 | // 判断容量是否超出限制 54 | if len(l.m) > l.maxsize { 55 | cur := l.Root 56 | for cur.next != nil { 57 | cur = cur.next 58 | } 59 | cur.pre.next = nil 60 | delete(l.m, cur.val) 61 | } 62 | } 63 | 64 | func (l *LRU) String() string { 65 | res := "" 66 | cur := l.Root 67 | for cur.next != nil { 68 | res += " " + strconv.Itoa(cur.next.val) 69 | cur = cur.next 70 | } 71 | return res 72 | } 73 | -------------------------------------------------------------------------------- /bloomfilter/bloomfilter.go: -------------------------------------------------------------------------------- 1 | package bloomfilter 2 | 3 | import ( 4 | "codelearning/bitmap" 5 | "github.com/spaolacci/murmur3" 6 | "math" 7 | ) 8 | 9 | type BloomFilter struct { 10 | bitset *bitmap.BitMap 11 | k int 12 | m int64 13 | } 14 | 15 | // m 代表布隆过滤器大小,也就是其中bitset的大小,k代表hash函数的个数 16 | func New(m int64, k int) *BloomFilter { 17 | return &BloomFilter{ 18 | bitset: bitmap.New(m), 19 | k: k, 20 | m: m, 21 | } 22 | } 23 | 24 | func (b *BloomFilter) Add(key string) { 25 | bitSetSize := b.m 26 | hashFunCount := b.k 27 | hash := murmur3.New128() 28 | hash.Write([]byte(key)) 29 | hash1, hash2 := hash.Sum128() 30 | combinedHash := hash1 31 | for i := 0; i < hashFunCount; i++ { 32 | b.bitset.Set((uint64ToInt64(combinedHash) & math.MaxInt64) % bitSetSize) 33 | combinedHash += hash2 34 | } 35 | } 36 | 37 | func (b *BloomFilter) MightContain(key string) bool { 38 | bitSetSize := b.m 39 | hashFunCount := b.k 40 | hash := murmur3.New128() 41 | hash.Write([]byte(key)) 42 | hash1, hash2 := hash.Sum128() 43 | combinedHash := hash1 44 | for i := 0; i < hashFunCount; i++ { 45 | if !b.bitset.Exits((uint64ToInt64(combinedHash) & math.MaxInt64) % bitSetSize) { 46 | return false 47 | } 48 | combinedHash += hash2 49 | } 50 | return true 51 | } 52 | 53 | func uint64ToInt64(num uint64) int64 { 54 | if num <= uint64(math.MaxInt64) { 55 | return int64(num) 56 | } 57 | return int64(num - uint64(math.MaxInt64) + 1) 58 | } 59 | -------------------------------------------------------------------------------- /heap/heap.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | type Heap struct { 4 | arr []int 5 | } 6 | 7 | func HeapInsert(arr []int) *Heap { 8 | h := &Heap{arr: make([]int, 0, len(arr))} 9 | for _, num := range arr { 10 | h.Insert(num) 11 | } 12 | return h 13 | } 14 | 15 | func Heapify(arr []int) *Heap { 16 | h := &Heap{arr: arr} 17 | lastNotLeaf := len(arr)/2 - 1 18 | for i := lastNotLeaf; i >= 0; i-- { 19 | h.ShiftDown(i) 20 | } 21 | return h 22 | } 23 | 24 | func (h *Heap) Insert(num int) { 25 | h.arr = append(h.arr, num) 26 | h.ShiftUp(len(h.arr) - 1) 27 | } 28 | 29 | // 从标号为index的节点开始做shifUp操作 30 | func (h *Heap) ShiftUp(index int) { 31 | if index == 0 { 32 | return 33 | } 34 | parent := (index - 1) / 2 35 | if h.arr[parent] < h.arr[index] { 36 | swap(h.arr, parent, index) 37 | h.ShiftUp(parent) 38 | } 39 | } 40 | 41 | // 删除并返回根节点 42 | func (h *Heap) Pop() int { 43 | num := h.arr[0] 44 | swap(h.arr, 0, len(h.arr)-1) 45 | h.arr = h.arr[:len(h.arr)-1] 46 | h.ShiftDown(0) 47 | return num 48 | } 49 | 50 | // 从标号为index的节点开始做shifDown操作 51 | func (h *Heap) ShiftDown(index int) { 52 | left := index*2 + 1 53 | right := index*2 + 2 54 | if left < len(h.arr) && right < len(h.arr) { 55 | if h.arr[left] >= h.arr[right] && h.arr[left] > h.arr[index] { 56 | swap(h.arr, left, index) 57 | h.ShiftDown(left) 58 | } 59 | if h.arr[right] > h.arr[left] && h.arr[right] > h.arr[index] { 60 | swap(h.arr, right, index) 61 | h.ShiftDown(right) 62 | } 63 | } 64 | if left >= len(h.arr) { 65 | return 66 | } 67 | if right >= len(h.arr) { 68 | if h.arr[left] > h.arr[index] { 69 | swap(h.arr, left, index) 70 | h.ShiftDown(left) 71 | } 72 | } 73 | } 74 | 75 | func swap(arr []int, i, j int) { 76 | tmp := arr[i] 77 | arr[i] = arr[j] 78 | arr[j] = tmp 79 | } 80 | -------------------------------------------------------------------------------- /skiplist/skiplitst.go: -------------------------------------------------------------------------------- 1 | package skiplist 2 | 3 | import "math/rand" 4 | 5 | type Node struct { 6 | val int 7 | next *Node 8 | down *Node 9 | } 10 | 11 | type Skiplist struct { 12 | head *Node 13 | } 14 | 15 | func Constructor() Skiplist { 16 | return Skiplist{head: &Node{val: -1, down: nil, next: nil}} 17 | } 18 | 19 | func (this *Skiplist) Search(target int) bool { 20 | cur := this.head 21 | for cur != nil { 22 | next := cur.next 23 | down := cur.down 24 | if cur.val == target { 25 | return true 26 | } 27 | if next != nil && next.val == target { 28 | return true 29 | } 30 | if next != nil && next.val > target { 31 | cur = down 32 | continue 33 | } 34 | if next != nil && next.val < target { 35 | cur = next 36 | } 37 | if next == nil { 38 | cur = down 39 | } 40 | } 41 | return false 42 | } 43 | 44 | func (this *Skiplist) Add(num int) { 45 | arr := make([]*Node, 0) 46 | cur := this.head 47 | for cur != nil { 48 | next := cur.next 49 | down := cur.down 50 | if next != nil && next.val >= num { 51 | arr = append(arr, cur) 52 | cur = down 53 | continue 54 | } 55 | if next != nil && next.val < num { 56 | cur = next 57 | } 58 | if next == nil { 59 | arr = append(arr, cur) 60 | cur = down 61 | } 62 | } 63 | inserted := true 64 | var down *Node 65 | for i := len(arr) - 1; i >= 0; i-- { 66 | if inserted { 67 | next := arr[i].next 68 | arr[i].next = &Node{val: num, next: next, down: down} 69 | inserted = rand.Intn(1000)%2 == 0 70 | down = arr[i].next 71 | } 72 | } 73 | // 添加新层 74 | if inserted { 75 | this.head = &Node{val: -1, down: this.head, next: &Node{val: num, next: nil, down: down}} 76 | } 77 | } 78 | 79 | func (this *Skiplist) Erase(num int) bool { 80 | cur := this.head 81 | deleted := false 82 | for cur != nil { 83 | next := cur.next 84 | down := cur.down 85 | if next != nil && next.val == num { 86 | cur.next = next.next 87 | next.down = nil 88 | next.next = nil 89 | cur = down 90 | deleted = true 91 | } 92 | if next != nil && next.val > num { 93 | cur = down 94 | continue 95 | } 96 | if next != nil && next.val < num { 97 | cur = next 98 | } 99 | if next == nil { 100 | cur = down 101 | } 102 | } 103 | if deleted { 104 | // 清理掉删除节点后没有元素的空层 105 | cur = this.head 106 | for cur.next == nil { 107 | this.head = cur.down 108 | cur = this.head 109 | } 110 | } 111 | return deleted 112 | } 113 | 114 | /** 115 | * Your Skiplist object will be instantiated and called as such: 116 | * obj := Constructor(); 117 | * param_1 := obj.Search(target); 118 | * obj.Add(num); 119 | * param_3 := obj.Erase(num); 120 | */ 121 | -------------------------------------------------------------------------------- /nfa/nfa_leetcode.go: -------------------------------------------------------------------------------- 1 | package nfa 2 | 3 | func isMatch(s string, p string) bool { 4 | nfa := New(p) 5 | return nfa.Match(s) 6 | } 7 | 8 | type NFA struct { 9 | final, start *State 10 | } 11 | 12 | const ( 13 | pTypeSingleLetter int = 1 14 | pTypeSingleAnyLetter int = 2 15 | pTypeAnyLetters int = 3 16 | pTypeSpecialLetters int = 4 17 | ) 18 | 19 | type Edge struct { 20 | IsEpsilon bool 21 | Ch string 22 | pType int 23 | } 24 | 25 | func (e *Edge) match(ch rune) bool { 26 | if e.IsEpsilon { 27 | return true 28 | } 29 | switch e.pType { 30 | case pTypeAnyLetters, pTypeSingleAnyLetter: 31 | return true 32 | default: 33 | if string(ch) == e.Ch { 34 | return true 35 | } 36 | return false 37 | } 38 | } 39 | 40 | type State struct { 41 | IsEnd bool 42 | Edges []*Edge 43 | Edge2State map[*Edge]*State 44 | } 45 | 46 | func (s *State) addEdge(state1 *State, edge *Edge) { 47 | s.Edges = append(s.Edges, edge) 48 | s.Edge2State[edge] = state1 49 | } 50 | 51 | func End(curState *State) bool { 52 | if curState.IsEnd { 53 | return true 54 | } 55 | for _, edge := range curState.Edges { 56 | if edge.IsEpsilon { 57 | return End(curState.Edge2State[edge]) 58 | } 59 | } 60 | return false 61 | } 62 | 63 | func (s *State) replaceState(state1 *State, newState *State) { 64 | for edge, st := range s.Edge2State { 65 | if st == state1 { 66 | s.Edge2State[edge] = newState 67 | } 68 | } 69 | } 70 | 71 | func New(words string) *NFA { 72 | start, end := newState(false), newState(true) 73 | start.addEdge(end, &Edge{IsEpsilon: true, Ch: ""}) 74 | 75 | nfa := &NFA{ 76 | final: end, 77 | start: start, 78 | } 79 | nfa.createNFA(words) 80 | return nfa 81 | } 82 | 83 | func newState(isend bool) *State { 84 | return &State{ 85 | IsEnd: isend, 86 | Edges: make([]*Edge, 0), 87 | Edge2State: make(map[*Edge]*State), 88 | } 89 | } 90 | 91 | func (n *NFA) createNFA(words string) { 92 | // 构建nfa 单个字符 字符* 字符. 93 | start, final := n.start, n.final 94 | for index := 0; index < len(words); index++ { 95 | ch := words[index] 96 | switch ch { 97 | case '.': 98 | if index+1 < len(words) && words[index+1] == '*' { 99 | begin, end := newState(false), newState(true) 100 | s := newState(false) 101 | s.addEdge(end, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 102 | s.addEdge(s, &Edge{IsEpsilon: false, Ch: ".", pType: pTypeAnyLetters}) 103 | begin.addEdge(s, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 104 | begin.addEdge(end, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 105 | start.replaceState(final, begin) 106 | start, final = s, end 107 | index++ 108 | continue 109 | } 110 | begin, end := newState(false), newState(true) 111 | begin.addEdge(end, &Edge{IsEpsilon: false, Ch: ".", pType: pTypeSingleAnyLetter}) 112 | start.replaceState(final, begin) 113 | start, final = begin, end 114 | default: 115 | if index+1 < len(words) && words[index+1] == '*' { 116 | begin, end := newState(false), newState(true) 117 | s := newState(false) 118 | n.final.addEdge(s, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 119 | s.addEdge(end, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 120 | s.addEdge(s, &Edge{IsEpsilon: false, Ch: string(ch), pType: pTypeSpecialLetters}) 121 | begin.addEdge(s, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 122 | begin.addEdge(end, &Edge{IsEpsilon: true, Ch: ".", pType: 0}) 123 | start.replaceState(final, begin) 124 | start, final = s, end 125 | index++ 126 | continue 127 | } 128 | begin, end := newState(false), newState(true) 129 | begin.addEdge(end, &Edge{IsEpsilon: false, Ch: string(ch), pType: pTypeSingleLetter}) 130 | start.replaceState(final, begin) 131 | start, final = begin, end 132 | } 133 | } 134 | } 135 | 136 | func (n *NFA) Match(inputs string) bool { 137 | index := matchHelper(n.start, []rune(inputs), 0) 138 | if index != len(inputs) { 139 | return false 140 | } 141 | return true 142 | } 143 | 144 | // 返回匹配到chars的数组长度, index为已经匹配到的索引长度 145 | func matchHelper(state *State, chars []rune, index int) int { 146 | index3 := index 147 | if state == nil { 148 | return index3 149 | } 150 | if index == len(chars) { 151 | if End(state) { 152 | // 匹配的长度达到了字符串的长度并且节点是最终状态,才算是匹配成功 153 | return len(chars) 154 | } else { 155 | return -1 156 | } 157 | } 158 | for _, edge := range state.Edges { 159 | //fmt.Println(edge.Ch) 160 | if edge.IsEpsilon { 161 | index3 = matchHelper(state.Edge2State[edge], chars, index) 162 | if index3 == len(chars) { 163 | return index3 164 | } 165 | } else if edge.match(chars[index]) { 166 | index3 = matchHelper(state.Edge2State[edge], chars, index+1) 167 | if index3 == len(chars) { 168 | return index3 169 | } 170 | } 171 | } 172 | return index3 173 | } 174 | --------------------------------------------------------------------------------