go环境安装

Go 计算机编程语言 Go(又称为Golang)是一种由Google开发的开源编程语言,于2009年首次公开发布。它旨在提供简洁、高效、可靠的软件开发解决方案。Go是一种静态强类型、编译型语言,具有很强的表达能力,得益于其并发机制,用它编写的程序能够非常有效地利用多核与联网的计算机。 主要特点 Go语言的设计目标是将静态语言的安全性和性能与动态语言的易用性相结合。它在语言层面提供了对协程的支持,特别适合编写高并发的项目。以下是Go语言的一些主要特点: 简洁、快速、安全:Go语言的语法接近C语言,但更简洁,编译速度非常快,且具有内置的垃圾回收功能。 并发支持:Go语言内置了轻量级进程(goroutine)、通道和select语句等并发原语,使得编写并发程序变得简单和高效。 模块化:Go语言采用模块化的方式组织代码,易于维护和重用。 跨平台:Go语言支持跨平台编译,可以在不同的操作系统上进行开发和部署。 安装 在Windows中安装Go: 安装包下载地址为:https://go.dev/dl/。 如果打不开可以使用这个地址:https://golang.google.cn/dl/。 运行第一个go程序 1 2 3 4 5 6 7 package main import "fmt" func main() { fmt.Println("Hello, World!") } 保存为hello.go 终端运行 1 2 $ go run hello.go Hello, World! 在同一命令提示符窗口中,第一次运行这个程序时,会耗时较多,在我的电脑上大约需要2~3秒,之后再运行这个程序就会很快,但关闭这个窗口,隔一段时间下次运行情况如初。 原因是这个命令会先编译 .go 文件,然后再运行编译后的可执行文件,所以第一次运行会比较慢。 可以使用go build命令来编译程序,然后再运行编译后的可执行文件,这样就不会每次都重新编译了。 1 2 3 $ go build hello.go $ ./hello Hello, World! VS Code运行 在VS Code中安装Go插件,然后打开hello.go文件,点击运行按钮,就可以运行这个程序了。 我遇到了几个问题: 1. VS Code 在安装 Go 语言的核心工具(gopls 和 dlv)时,无法连接到官方的 Go 模块代理服务器(proxy.golang.org),导致网络连接超时失败。 报错中有dial tcp 142.251.45.145:443: connectex: A connection attempt failed ...

January 28, 2026 · 1 min · farmer3-c

爬取中国工商银行人民币即期外汇牌价数据

爬取单日数据 前期准备 我要爬取的网站是 https://www.icbc.com.cn/ICBC/%e9%87%91%e8%9e%8d%e4%bf%a1%e6%81%af/%e8%a1%8c%e6%83%85%e6%95%b0%e6%8d%ae/%e4%ba%ba%e6%b0%91%e5%b8%81%e5%8d%b3%e6%9c%9f%e5%a4%96%e6%b1%87%e7%89%8c%e4%bb%b7/ 数据是这样的:币种、银行买入价、银行卖出价、发布时间 环境:python 3.12.2 寻找网络请求接口 在浏览器中按F12打开开发者工具,然后点击Network,勾选 Preserve log 选择 Fetch / XHR XMLHttpRequest (XHR) 和 Fetch API都是网页向服务器发起 HTTP 请求的机制。Fetch API 是一种现代的、基于 Promise 的替代方案,用于取代老旧的、基于回调的 XHR,它提供了更简洁的语法和更适合现代网页开发的功能。 手动操作页面: 选择一个日期(比如 2021-01-25) 点击【查询】 Network 列表里 新出现的 POST 请求 可以确定工商银行新版 PAPI 的“历史外汇牌价接口”:POST https://papi.icbc.com.cn/exchanges/ns/history 如何使用接口 请求方式 POST Content-Type: application/json 请求体 1 2 3 4 5 { "date": "2021-01-13", "currType": "", "serverType": "1" } 👉 这个接口不支持“时间区间” 👉 需要一天一天请求 编写代码 点击展开/折叠代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import requests url = "https://papi.icbc.com.cn/exchanges/ns/history" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Content-Type": "application/json", "Origin": "https://www.icbc.com.cn", "Referer": "https://www.icbc.com.cn/ICBC/%E9%87%91%E8%9E%8D%E4%BF%A1%E6%81%AF/%E8%A1%8C%E6%83%85%E6%95%B0%E6%8D%AE/%E4%BA%BA%E6%B0%91%E5%B8%81%E5%8D%B3%E6%9C%9F%E5%A4%96%E6%B1%87%E7%89%8C%E4%BB%B7/" } payload = { "date": "2021-01-13", "currType": "", "serverType": "1" } r = requests.post(url, headers=headers, json=payload, timeout=10) r.raise_for_status() print(r.json()) 报错:[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] 当前的 Python + OpenSSL 与工行 PAPI 服务器的 TLS 协商不兼容 更准确地说: 请求触发了“不安全的旧式 TLS 重新协商”,而 Python 默认已经禁止它 为什么浏览器能访问,我的 Python 不能? 浏览器(Chrome / Edge): ...

January 20, 2026 · 5 min · farmer3-c

翻转树上最少边

翻转树上最少边 给你一棵包含 n 个节点的 无向树,节点编号从 0 到 n - 1。该树由长度为 n - 1 的二维整数数组 edges 表示,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。 另外给你两个长度为 n 的 二进制 字符串 start 和 target。对于每个节点 x,start[x] 是其初始颜色,而 target[x] 是其目标颜色。 在一次操作中,你可以选择下标为 i 的一条边并 翻转 它的两个端点。也就是说,如果这条边是 [u, v],那么节点 u 和 v 的颜色 各自 从 ‘0’ 变为 ‘1’,或者从 ‘1’ 变为 ‘0’。 返回一个边下标数组,执行这些边对应的操作可以将 start 转换为 target。在所有有效序列中找出 长度最短 的序列,以 升序 返回边下标。 如果无法将 start 转换为 target,则返回一个仅包含单个元素 -1 的数组。 ...

January 19, 2026 · 2 min · farmer3-c

交替按位异或分割的数目

3811.交替按位异或分割的数目 给你一个整数数组 nums 以及两个 互不相同 的整数 target1 和 target2。nums 的一个 分割 是指将其划分为一个或多个 连续且非空 的块,这些块在不重叠的情况下覆盖整个数组。 如果一个分割中各块元素的 按位异或 结果在 target1 和 target2 之间 交替 出现,且以 target1 开始,则称该分割是 有效的。 形式上,对于块 b1, b2, … : XOR(b1) = target1 XOR(b2) = target2(如果存在) XOR(b3) = target1,以此类推。 返回 nums 的有效分割方案数,结果对 $10^9 $+ 7 取余。 注意: 如果单个块的 按位异或 结果等于 target1,则该分割也是有效的。 1 <= nums.length <= $10^5$ 0 <= nums[i], target1, target2 <= $10^5$ target1 != target2 思路 方法一:递归+记忆化搜索 点击展开/折叠代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Solution { int mod = 1e9 + 7, t[2]; vector<vector<long long>> memo; long long dfs(int i, int state, vector<int> &nums) { if (i == nums.size()) { return 0; } if (memo[i][state] != -1) { return memo[i][state]; } long long res = 0; int cur = 0; for (int j = i; j < nums.size(); j++) { cur ^= nums[j]; if (cur == t[state]) { if (j == nums.size() - 1) { res = (res + 1) % mod; } else { res = (res + dfs(j + 1, state ^ 1, nums)) % mod; } } } return memo[i][state]=res; } public: int alternatingXOR(vector<int> &nums, int target1, int target2) { int n = nums.size(); t[0] = target1; t[1] = target2; memo.resize(n, vector<long long>(2, -1)); return dfs(0, 0, nums); } }; 时间复杂度:O(n),其中n为数组nums的长度。 空间复杂度:O(n),需要使用一个二维数组memo来存储中间结果。 不足以通过所有测试用例,超时。 ...

January 19, 2026 · 2 min · farmer3-c

查找并重命名文件

下面是实现查找并重命名文件的C程序,使用了apue.h库中的函数和数据结构。 该程序支持查找指定目录下的所有文件,并将指定文件名的文件重命名为"pass"。 程序会输出重命名的文件数量。 点击展开/折叠代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 #include "apue.h" #include <dirent.h> #include <limits.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> typedef int Myfunc(const char *, const struct stat *, int); static Myfunc myfunc_rename; static int dopath(Myfunc *); static int myftw(char *, Myfunc *); static char *fullpath; // 存储文件完整路径 static char *target_filename; // 要查找并重命名的目标文件名 static int rename_count = 0; // 成功重命名的文件数 // 文件类型标记 #define FTW_F 1 /* 普通文件 */ #define FTW_D 2 /* 目录 */ #define FTW_DNR 3 /* 不可读目录 */ #define FTW_NS 4 /* 无法stat的文件 */ int main(int argc, char *argv[]) { int ret; // 校验参数:支持 myfind <指定目录> <要改名的文件名> if (argc != 3) { err_quit("usage: myfind <target_directory> <filename_to_rename>"); } target_filename = argv[2]; rename_count = 0; ret = myftw(argv[1], myfunc_rename); if (rename_count == 0) { printf("未找到名为 '%s' 的文件,无需重命名\n", target_filename); } else { printf("成功将 %d 个文件重命名为 'pass'\n", rename_count); } exit(ret); } static int myftw(char *pathname, Myfunc *func) { size_t len; fullpath = path_alloc(&len); // 从apue库获取路径缓冲区 strncpy(fullpath, pathname, len); fullpath[len-1] = 0; // 确保字符串终止 return(dopath(func)); } static int dopath(Myfunc *func) { struct stat statbuf; struct dirent *dirp; DIR *dp; int ret; char *ptr; // 获取文件属性失败 if (lstat(fullpath, &statbuf) < 0) return(func(fullpath, &statbuf, FTW_NS)); // 如果是普通文件,执行重命名逻辑 if (S_ISDIR(statbuf.st_mode) == 0) return(func(fullpath, &statbuf, FTW_F)); // 如果是目录,先执行回调(无实际操作) if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) return(ret); // 拼接子目录路径 ptr = fullpath + strlen(fullpath); *ptr++ = '/'; *ptr = 0; // 打开目录失败 if ((dp = opendir(fullpath)) == NULL) return(func(fullpath, &statbuf, FTW_DNR)); // 遍历目录下的所有文件/子目录 while ((dirp = readdir(dp)) != NULL) { // 跳过.和.. if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) continue; // 拼接子文件路径 strcpy(ptr, dirp->d_name); // 递归处理子文件/子目录 if ((ret = dopath(func)) != 0) break; } // 恢复路径(移除最后拼接的子文件名) ptr[-1] = 0; // 关闭目录 if (closedir(dp) < 0) err_ret("无法关闭目录: %s", fullpath); return(ret); } // 查找目标文件并将其重命名为pass static int myfunc_rename(const char *pathname, const struct stat *statptr, int type) { // 仅处理普通文件 if (type != FTW_F) return 0; // 提取文件名(路径最后一个/后的部分) char *filename = strrchr(pathname, '/'); if (filename == NULL) { filename = (char *)pathname; // 无/,直接是文件名 } else { filename++; // 跳过/,指向实际文件名 } // 匹配到目标文件,执行重命名 if (strcmp(filename, target_filename) == 0) { // 拼接新路径:原目录 + /pass char new_path[PATH_MAX]; strncpy(new_path, pathname, strrchr(pathname, '/') - pathname + 1); strcat(new_path, "pass"); // 执行重命名 if (rename(pathname, new_path) == 0) { printf("成功重命名: %s -> %s\n", pathname, new_path); rename_count++; } else { err_ret("重命名失败: %s", pathname); } } return 0; } UNIX系统中路径的操作与修改 这个程序实现了在指定目录下查找并重命名特定文件的功能,展示了多种路径操作技术。 ...

January 13, 2026 · 4 min · farmer3-c

判断质数汇编程序编写

以下面的代码为例,说明如何用汇编语言判断一个数是否为素数,从而进行汇编语言的学习。 点击展开/折叠代码 .MODEL SMALL .STACK 100H .DATA msg_input DB ‘Please input a number: $' msg_prime DB 0DH, 0AH, 'It is a prime number.$’ msg_not DB 0DH, 0AH, ‘It is not a prime number.$’ num DW 0 .CODE START: MOV AX, @DATA MOV DS, AX ; 1. 显示输入提示 LEA DX, msg_input MOV AH, 09H INT 21H ; 2. 读取数字 (读取一个十进制数) CALL READ_NUM MOV num, AX ; 3. 判断素数逻辑 ; 如果 n < 2,不是素数 CMP AX, 2 JL NOT_PRIME JE IS_PRIME ; 2 是素数 ; 循环判断: 从 2 到 n-1 MOV CX, 2 ; CX 是除数 CHECK_LOOP: MOV AX, num XOR DX, DX ; 清除高位 DIV CX ; AX / CX, 余数在 DX ...

January 12, 2026 · 3 min · farmer3-c

convex review

Lecture 1: Unconstrained Optimization for Differentiable Functions 几个无限制可微问题的优化: 对于一般的函数求极值问题: 一个变量的函数可以求导,极值一般在导函数的零点。 如:求极小值$f(x)=x^2-1$ 多个变量的函数可以求偏导,极值一般在偏导函数的零点。 如:求极值$f(x,y)=x^3-y^3+3x^2+3y^2-9x$ 对得到的四个驻点进行的二阶导数检验(Hessian 判别法) $$|H|=f_{xx}f_{yy}-(f_{xy})^2$$令$a=f_{xx}$ 若 ∣H∣>0且 a>0 → 局部极小值(Ext. small) 若 ∣H∣>0 且 a<0 → 局部极大值(Ext. large) 若 ∣H∣<0 → 鞍点(uncertain,即非极值点) 若 ∣H∣=0 → 无法判断(需要更高阶检验) 梯度下降求极大/极小值: 对一个复杂的函数求极值是一件困难的事,梯度下降可以使它变得简单。 $$ \begin{aligned} f(x) &\approx f(x_0)+(x-x_0)f'(x_0) \\ f(x) &= f(x_0)-\Delta xf'(x_0) \end{aligned} $$$\implies x=x_0-\Delta x$ 设置一个学习率a,或者叫步长, $\Delta x=a f'(x_0)$ 然后就是一个迭代的过程: $x_{k+1}=x_k-\Delta x_k$ $f'(x_k)=0$时到达极值点。 牛顿法-I解决等式限制的优化: 思想也是迭代。 如:$e^x-2x^2+3x-4=0$ 迭代$(x_n,f(x_n))$ ${y=f'(x_n)(x-x_n)+f(x_n)} \xrightarrow {\text{y → 0}}{x=x_n-\frac{f(x_n)}{f'(x_n)}}$ ...

December 11, 2025 · 7 min · farmer3-c

matlab tutorial

1.Basic Arithmetic 直接在命令行输入算式,结果存入ans变量中 如: >> 1+2 ans = 3 2.Variables 设置变量的值,存入系统中,之后可以调用 >> x=7 x = 7 >> x+3 ans = 10 >> 3.Change Format format [数据类型] 可以改变运算的结果数据类型 >> 1/3 ans = 0.3333 >> format short >> 1/3 ans = 0.3333 >> format long >> 1/3 ans = 0.333333333333333 >> 4.Remove Variables clear [变量名] 用于清楚变量 >> x x = 7 >> clear x >> x 函数或变量 'x' 无法识别。 >> 5.Clear Specific Variables 高级一点的Remove Variables之类的用法 >> x3=3 x3 = 3 >> >> clear x* >> x3=3 x3 = 3 >> who 您的变量为: ans x3 >> whos Name Size Bytes Class Attributes ans 1x1 8 double x3 1x1 8 double >> 6. Pre-Defined Constants 系统中预定义的变量 ...

November 22, 2025 · 5 min · farmer3-c

静态随机存储器

静态随机存储器实验 实验目的 (1) 掌握静态随机存储器 RAM 工作特性及数据的读写方法。 (2) 基于信号时序图,了解读写静态随机存储器的原理。 实验设备 PC 机一台,TDX-CMX 实验系统一套。 实验原理 实验所用的静态存储器由一片 6116(2K×8bit)构成(位于 MEM 单元),如图 2-1-1 所示。 6116 有三个控制线:CS(片选线)、OE(读线)、WE(写线),其功能如表 2-1-1 所示,当片选有效(CS=0)时,OE=0 时进行读操作,WE=0 时进行写操作,本实验将 CS 常接地。 实验原理图如图 2-1-2 所示,存储器数据线接至 CPU 内总线,内总线上接有 8 个 LED 灯显示 D7…D0 的内容。地址线接至地址总线,地址总线上接有 8 个 LED 灯显示 A7…A0 的内容,地址由地址锁存器(74LS273,内嵌于 ABI 单元)给出。数据开关(位于 CON 单元的 SD17..SD10)经一个三态门(74LS245)连至 CPU 内总线,分时给出地址和数据。地址寄存器为 8 位,接入存储器的地址 A7…A0,高三位地址 A10…A8 接地,所以其实际容量为 256 字节。 实验箱中所有单元的时序都连接至时序与操作台单元,CLR 都连接至 CON 单元的 CLR 按钮。实验时 T3 由时序单元给出,其余信号由 CON 单元的对应二进制开关模拟给出,其中 RD、 WR 低有效,SW_B 低有效,LDAR 高有效。 ...

November 5, 2025 · 2 min · farmer3-c

线段树

线段树是一种特殊的数据结构,它可以在 $O(\log n)$ 的时间复杂度内实现单点修改、区间修改、区间查询(区间求和,求区间最大值,求区间最小值)等操作。 最简单的线段树的构建: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <iostream> #include <vector> using namespace std; // 定义线段树的节点 struct Node { int l, r; // 左右子节点的下标 int sum; // 区间和 }; vector<Node> tree; // 存储线段树的数组 // 构建线段树 void build(int l, int r, int index, vector<int>& nums) { tree[index].l = l; tree[index].r = r; if (l == r) { // 叶子节点 tree[index].sum = nums[l]; return; } int mid = (l + r) / 2; build(l, mid, index * 2, nums); // 构建左子树 build(mid + 1, r, index * 2 + 1, nums); // 构建右子树 tree[index].sum = tree[index * 2].sum + tree[index * 2 + 1].sum; // 计算区间和 } // 区间查询 int query(int l, int r, int index) { if (tree[index].l >= l && tree[index].r <= r) { // 当前区间完全包含在查询区间内 return tree[index].sum; } int mid = (tree[index].l + tree[index].r) / 2; int sum = 0; if (l <= mid) { // 查询区间和左子树有交集 sum += query(l, r, index * 2); } if (r > mid) { // 查询区间和右子树有交集 sum += query(l, r, index * 2 + 1); } return sum; } // 单点修改 void update(int pos, int val, int index) { if (tree[index].l == tree[index].r) { // 叶子节点 tree[index].sum = val; return; } int mid = (tree[index].l + tree[index].r) / 2; if (pos <= mid) { // 修改的位置在左子树 update(pos, val, index * 2); } else { // 修改的位置在右子树 update(pos, val, index * 2 + 1); } tree[index].sum = tree[index * 2].sum + tree[index * 2 + 1].sum; // 更新区间和 } int main() { vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 原始数组 int n = nums.size(); // 数组长度 tree.resize(n * 4); // 线段树的大小为 4n build(0, n - 1, 1, nums); // 构建线段树 cout << query(0, 4, 1) << endl; // 查询区间 [0, 4] 的和 update(2, 10, 1); // 将第 2 个元素修改为 10 cout << query(0, 4, 1) << endl; // 查询区间 [0, 4] 的和 return 0; } 构建解释: 递归地将数组分为左右两个子数组,直到子数组长度为 1,此时该子数组的区间和就是该子数组的元素值。 ...

October 20, 2025 · 3 min · farmer3-c