相关信息

本章节主要学习网络知识

短连接

  • 模式:建立连接 -> 发送数据 -> 关闭连接。
  • 背景:早期的 HTTP/1.0。每请求一个网页上的图片或 CSS,都要经历一次 TCP 三次握手和四次挥手。
  • 缺点:开销极大。频繁地创建和销毁连接非常耗费 CPU 和内存资源。

长连接

  • 模式:建立连接 -> 发送数据 -> 保持连接 -> 发送数据 -> ... -> 关闭连接。
  • 背景:HTTP/1.1 默认开启。在 HTTP Header 中加入 Connection: keep-alive。
  • 特点:
    • 复用:同一个 TCP 连接可以发送多个 HTTP 请求。
    • 半双工:虽然连接没断,但依然是“请求-响应”模式。必须客户端先问,服务端才能答。
    • 阻塞:前面的请求没处理完,后面的请求就得排队(Head-of-line blocking)

WebSocket (全双工长连接)

  • 模式:HTTP 握手升级 -> 建立持久 TCP 连接 -> 双向实时传输。
  • 背景:为了解决“服务端主动推送到客户端”的问题(如聊天、实时股票)。
  • 特点:
    • 全双工:客户端和服务器可以同时给对方发消息,不需要等对方回应。
    • 协议升级:它开始时借用 HTTP 的 80/443 端口进行握手,握手成功后就“脱离” HTTP,转为 WebSocket 协议。
    • 轻量:数据头非常小,适合频繁发送短消息。
2026-01-150

相关信息

堆栈的区别

内存分配的区别

  • 栈内存
    • 分配方式:由编译器自动分配和释放
    • 存储内容: 函数的局部变量、参数值、返回地址
    • 生长方向: 向低地址生长
    • 连续的内存区域
    • 异常类型: 栈溢出
    • 访问速度: 快
  • 堆内存
    • 分配方式: 由程序员手动申请和释放(go中的new),go中由垃圾回收期处理
    • 存储内容: 动态生成的对象,大型数组
    • 访问速度:慢(随机访问较多)
  • go中堆栈的情况

相关信息

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

js
package main import ( "fmt" ) // 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 // 最近公共祖先的定义:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x, // 满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” // 例如,如下二叉树: Integer[] levelOrder = {3,5,1,6,2,0,8,null,null,7,4}; // 3 // 5 1 // 6 2 0 8 // 7 4 type TreeNode struct { Val int Left *TreeNode Right *TreeNode } func main() { // 构建二叉树 root := &TreeNode{Val: 3} root.Left = &TreeNode{Val: 5} root.Right = &TreeNode{Val: 1} root.Left.Left = &TreeNode{Val: 6} root.Left.Right = &TreeNode{Val: 2} root.Right.Left = &TreeNode{Val: 0} root.Right.Right = &TreeNode{Val: 8} root.Left.Right.Left = &TreeNode{Val: 7} root.Left.Right.Right = &TreeNode{Val: 4} // 测试最近公共祖先 p := root.Left.Right.Left q := root.Left.Right.Right lca := lowestCommonAncestor(root, p, q) fmt.Println("最近公共祖先:", lca.Val) // fmt.Println("Hello world!") } func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { if root == nil || root == p || root == q { return root } left := lowestCommonAncestor(root.Left, p, q) right := lowestCommonAncestor(root.Right, p, q) if left != nil && right != nil { return root } if left != nil { return left } return right }
2025-12-150

相关信息

接雨水,这道题最大的问题在于理解怎么才能接到雨水

接雨水其实就是看当前位置的左右是否存在格挡,存在格挡可以存雨水,能存放的最大容积为左右出现的格挡的最大高度

第一步 声明变量初始值 left right maxLeft Maxleft res

第二步 从左右两边开始对比: for left < right {}

第三步 if height[left] < height[right] 则处理左边,否则处理右边

第四步 处理左边 如果当前位置(left)大于等于 maxLeft 则更新maxLeft 否则说明左边的高度是超出当前位置的,可以进行容积增加: maxLeft - height[left]

右边的逻辑和左边一样,发现右边的格挡更高,则增加高度差,否则更新高度最大值(当前值比maxRight更大)

js
func trap(height []int) int { left, right := 0, len(height)-1 leftMax, rightMax := 0, 0 res := 0 for left < right { if height[left] < height[right] { if height[left] >= leftMax { leftMax = height[left] } else { res += leftMax - height[left] } left++ } else { if height[right] >= rightMax { rightMax = height[right] } else { res += rightMax - height[right] } right-- } } return res }

相关信息

算法实现-golang实现交替打印数字字母

该题的关键在意通过channel进行控制

  • 声明一个数字ch,一个字母ch
  • 分别启动一个go 协程, 一直读取channel,读取到则进行消费,消费后,写入对方的信号到通道中

相关信息

golang基础学习

Go 程序启动顺序

js
1. 编译期(build) 2. 生成可执行文件 3. 运行时启动(runtime start) 4. 初始化 package 5. 执行 init() 6. 执行 main.main()

init的执行时机

一般可以理解为main执行之前

js
1️. var 变量初始化(初始化的真正执行)(全局变量,也就是package级别的变量) 2️. init() 3️. main()
  • 备注: 局部变量是在函数执行调用时,才会被触发声明

编译时做了那些事情

js
1. 语法检查 2. 类型检查 3. 依赖分析 4. 变量初始化代码生成(决定怎么初始化、按什么顺序初始化) 5. init 调用链生成 6. main 入口标记

字符串的小问题

go
①可以用==比较 ②不可以通过下标的方式改变某个字符,字符串是只读的 ③不能和nil比较
2025-11-270

相关信息

内存四驱

代码区:存放代码 全局区:常量+全局变量。最终在进程退出时,由操作系统回收。 堆区:空间充裕,数据存放时间较久。一般由开发者分配,启动Golang的GC由GC清除机制自动回收。 栈区:空间较小,要求数据读写性能高,数据存放时间较短暂。由编译器自动分配和释放,存放函数的参数值、局部变量、返回值等、局部变量等(局部变量如果产生逃逸现象,可能会挂在在堆区)

相关信息

相关信息

  • 首先需要用ctrl + z将任务暂停
  • 然后执行下面的操作
js
bg 1&&disown %1