Merge branch 'milestone-20260401-学习笔记' of http://39.101.133.168:8807/majun/practiceGit into milestone-20260401-学习笔记
-
1.gitIgnore
-
BIN刘林林学习笔记/~$林4.2股票.docx
-
BIN刘林林学习笔记/刘林林4.2git.docx
-
BIN刘林林学习笔记/刘林林4.2股票.docx
-
0吴迎召学习笔记/wu.txt
-
150吴迎召学习笔记/吴迎召3.28学习笔记(技术部分).txt
-
57吴迎召学习笔记/吴迎召3.28学习笔记(金融知识).txt
-
77吴迎召学习笔记/吴迎召3.30学习笔记(技术部分).txt
-
39吴迎召学习笔记/吴迎召3.30学习笔记(金融知识).txt
-
45吴迎召学习笔记/吴迎召3.31学习笔记(技术部分).txt
-
66吴迎召学习笔记/吴迎召3.31学习笔记(金融部分).txt
-
116吴迎召学习笔记/吴迎召4.01学习笔记(技术部分).txt
-
12吴迎召学习笔记/吴迎召4.01学习笔记(金融部分).txt
-
BIN周新忠学习笔记/3.26/3.26周新忠.doc
-
BIN周新忠学习笔记/3.26/img_v3_02105_38857810-df73-49e4-bd95-da64f6ba747g.jpg
-
BIN周新忠学习笔记/3.26/img_v3_02105_7aaf57cd-1bac-4557-ad84-1ca9423f2eeg.jpg
-
BIN周新忠学习笔记/3.26/img_v3_02105_aed06a45-10b1-498c-842a-6e09ad05ff8g.jpg
-
BIN周新忠学习笔记/3.26/img_v3_02105_c300e793-9fa7-48a8-b698-075ac795e58g.jpg
-
BIN周新忠学习笔记/3.26/img_v3_02106_0c6b6038-891c-4657-a3cb-414c02ff1fbg.jpg
-
BIN周新忠学习笔记/3.27/1.jpg
-
BIN周新忠学习笔记/3.27/2.jpg
-
47周新忠学习笔记/3.27/3.27周新忠.md
-
BIN周新忠学习笔记/3.27/3.jpg
-
BIN周新忠学习笔记/3.27/4.jpg
-
BIN周新忠学习笔记/3.28/1.jpg
-
BIN周新忠学习笔记/3.28/2.jpg
-
180周新忠学习笔记/3.28/3.28.md
-
BIN周新忠学习笔记/3.28/3.jpg
-
BIN周新忠学习笔记/3.28/4.jpg
-
BIN周新忠学习笔记/3.28/5.jpg
-
BIN周新忠学习笔记/3.28/6.jpg
-
BIN周新忠学习笔记/3.28/7.jpg
-
BIN周新忠学习笔记/3.30/1.jpg
-
BIN周新忠学习笔记/3.30/2.jpg
-
BIN周新忠学习笔记/3.30/3.jpg
-
BIN周新忠学习笔记/3.30/4.jpg
-
BIN周新忠学习笔记/3.30/5.jpg
-
BIN周新忠学习笔记/3.30/6.jpg
-
145周新忠学习笔记/3.30/周新忠3.30笔记.md
-
BIN周新忠学习笔记/3.31/1.jpg
-
BIN周新忠学习笔记/3.31/2.jpg
-
BIN周新忠学习笔记/3.31/3.jpg
-
116周新忠学习笔记/3.31/周新忠笔记3.31.md
-
1周新忠学习笔记/4.1/gf_demo_02/.gitattributes
-
19周新忠学习笔记/4.1/gf_demo_02/.gitignore
-
7周新忠学习笔记/4.1/gf_demo_02/Makefile
-
6周新忠学习笔记/4.1/gf_demo_02/README.MD
-
57周新忠学习笔记/4.1/gf_demo_02/api/user/v1/user.go
-
38周新忠学习笔记/4.1/gf_demo_02/go.mod
-
70周新忠学习笔记/4.1/gf_demo_02/go.sum
-
13周新忠学习笔记/4.1/gf_demo_02/hack/config.yaml
-
20周新忠学习笔记/4.1/gf_demo_02/hack/hack-cli.mk
-
75周新忠学习笔记/4.1/gf_demo_02/hack/hack.mk
-
30周新忠学习笔记/4.1/gf_demo_02/internal/cmd/cmd.go
-
3周新忠学习笔记/4.1/gf_demo_02/internal/consts/consts.go
-
98周新忠学习笔记/4.1/gf_demo_02/internal/controller/user/user.go
-
0周新忠学习笔记/4.1/gf_demo_02/internal/dao/.gitkeep
-
27周新忠学习笔记/4.1/gf_demo_02/internal/dao/course.go
-
83周新忠学习笔记/4.1/gf_demo_02/internal/dao/internal/course.go
-
83周新忠学习笔记/4.1/gf_demo_02/internal/dao/internal/stock.go
-
85周新忠学习笔记/4.1/gf_demo_02/internal/dao/internal/user.go
-
75周新忠学习笔记/4.1/gf_demo_02/internal/dao/internal/user_course.go
-
27周新忠学习笔记/4.1/gf_demo_02/internal/dao/stock.go
-
27周新忠学习笔记/4.1/gf_demo_02/internal/dao/user.go
-
27周新忠学习笔记/4.1/gf_demo_02/internal/dao/user_course.go
-
0周新忠学习笔记/4.1/gf_demo_02/internal/logic/.gitkeep
-
12周新忠学习笔记/4.1/gf_demo_02/internal/logic/course/course.go
-
9周新忠学习笔记/4.1/gf_demo_02/internal/logic/logic.go
-
143周新忠学习笔记/4.1/gf_demo_02/internal/logic/user/user.go
-
0周新忠学习笔记/4.1/gf_demo_02/internal/model/.gitkeep
-
9周新忠学习笔记/4.1/gf_demo_02/internal/model/claim.go
-
0周新忠学习笔记/4.1/gf_demo_02/internal/model/do/.gitkeep
-
21周新忠学习笔记/4.1/gf_demo_02/internal/model/do/course.go
-
21周新忠学习笔记/4.1/gf_demo_02/internal/model/do/stock.go
-
22周新忠学习笔记/4.1/gf_demo_02/internal/model/do/user.go
-
16周新忠学习笔记/4.1/gf_demo_02/internal/model/do/user_course.go
-
0周新忠学习笔记/4.1/gf_demo_02/internal/model/entity/.gitkeep
-
19周新忠学习笔记/4.1/gf_demo_02/internal/model/entity/course.go
-
19周新忠学习笔记/4.1/gf_demo_02/internal/model/entity/stock.go
-
20周新忠学习笔记/4.1/gf_demo_02/internal/model/entity/user.go
-
11周新忠学习笔记/4.1/gf_demo_02/internal/model/entity/user_course.go
-
16周新忠学习笔记/4.1/gf_demo_02/internal/model/models.go
-
1周新忠学习笔记/4.1/gf_demo_02/internal/packed/packed.go
-
0周新忠学习笔记/4.1/gf_demo_02/internal/service/.gitkeep
-
65周新忠学习笔记/4.1/gf_demo_02/internal/service/JWTMiddleware.go
-
21周新忠学习笔记/4.1/gf_demo_02/internal/service/encode_pass.go
-
7周新忠学习笔记/4.1/gf_demo_02/internal/service/encode_pass_test.go
-
40周新忠学习笔记/4.1/gf_demo_02/internal/service/user.go
-
BIN周新忠学习笔记/4.1/gf_demo_02/main.exe~
-
17周新忠学习笔记/4.1/gf_demo_02/main.go
-
21周新忠学习笔记/4.1/gf_demo_02/manifest/deploy/kustomize/base/deployment.yaml
-
8周新忠学习笔记/4.1/gf_demo_02/manifest/deploy/kustomize/base/kustomization.yaml
-
12周新忠学习笔记/4.1/gf_demo_02/manifest/deploy/kustomize/base/service.yaml
-
14周新忠学习笔记/4.1/gf_demo_02/manifest/deploy/kustomize/overlays/develop/configmap.yaml
-
10周新忠学习笔记/4.1/gf_demo_02/manifest/deploy/kustomize/overlays/develop/deployment.yaml
-
14周新忠学习笔记/4.1/gf_demo_02/manifest/deploy/kustomize/overlays/develop/kustomization.yaml
-
16周新忠学习笔记/4.1/gf_demo_02/manifest/docker/Dockerfile
-
8周新忠学习笔记/4.1/gf_demo_02/manifest/docker/docker.sh
-
0周新忠学习笔记/4.1/gf_demo_02/manifest/i18n/.gitkeep
-
0周新忠学习笔记/4.1/gf_demo_02/manifest/protobuf/.keep-if-necessary
@ -0,0 +1 @@ |
|||||
|
.idea/ |
||||
@ -0,0 +1,150 @@ |
|||||
|
1. 核心定义与特点 |
||||
|
MySQL 是Oracle 公司维护的开源关系型数据库管理系统(RDBMS),基于标准 SQL 语言,是 Web 开发、企业级业务最主流的数据库。 |
||||
|
核心优势:开源免费、跨平台、性能优异、支持事务、高可用生态完善、社区活跃。 |
||||
|
主流版本: |
||||
|
5.7:企业广泛使用的稳定版,长期支持,兼容性好 |
||||
|
8.0:当前最新稳定版,性能大幅提升,新增窗口函数、CTE、原子 DDL、原生 JSON 支持,默认 InnoDB 引擎,默认字符集 utf8mb4,移除查询缓存。 |
||||
|
字段约束 |
||||
|
NOT NULL:非空约束,建议所有字段都设置,避免 NULL 值带来的性能问题 |
||||
|
UNIQUE:唯一约束,字段值唯一,允许 NULL |
||||
|
PRIMARY KEY:主键约束,非空 + 唯一,一张表仅一个 |
||||
|
DEFAULT:默认值,字段未赋值时的兜底值 |
||||
|
CHECK:检查约束,MySQL 8.0.16 + 正式支持,限制字段取值范围 |
||||
|
二、SQL 核心语法 |
||||
|
SQL 分为五大类:DDL(数据定义)、DML(数据操作)、DQL(数据查询)、DCL(数据控制)、TCL(事务控制) |
||||
|
1. DDL:操作库、表结构 |
||||
|
-- 创建数据库 |
||||
|
CREATE DATABASE IF NOT EXISTS test_db |
||||
|
DEFAULT CHARACTER SET utf8mb4 |
||||
|
DEFAULT COLLATE utf8mb4_general_ci; |
||||
|
-- 删除数据库 |
||||
|
DROP DATABASE IF EXISTS test_db; |
||||
|
-- 查看数据库创建语句 |
||||
|
SHOW CREATE DATABASE test_db; |
||||
|
-- 创建表(企业级规范示例) |
||||
|
CREATE TABLE IF NOT EXISTS `user` ( |
||||
|
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', |
||||
|
`username` VARCHAR(50) NOT NULL COMMENT '用户名', |
||||
|
`phone` CHAR(11) NOT NULL COMMENT '手机号', |
||||
|
`age` TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄', |
||||
|
`gender` ENUM('男','女','未知') DEFAULT '未知' COMMENT '性别', |
||||
|
`balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '账户余额', |
||||
|
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
||||
|
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
||||
|
PRIMARY KEY (`id`), -- 主键索引 |
||||
|
UNIQUE KEY `uk_phone` (`phone`), -- 唯一索引 |
||||
|
KEY `idx_username` (`username`) -- 普通索引 |
||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; |
||||
|
-- 修改表结构 |
||||
|
ALTER TABLE `user` ADD COLUMN `email` VARCHAR(100) NOT NULL COMMENT '邮箱' AFTER `phone`; -- 新增字段 |
||||
|
ALTER TABLE `user` MODIFY COLUMN `age` TINYINT UNSIGNED DEFAULT 18 COMMENT '年龄'; -- 修改字段属性 |
||||
|
ALTER TABLE `user` DROP COLUMN `email`; -- 删除字段 |
||||
|
ALTER TABLE `user` ADD INDEX `idx_create_time` (`create_time`); -- 新增索引 |
||||
|
ALTER TABLE `user` DROP INDEX `idx_create_time`; -- 删除索引 |
||||
|
-- 删除表 |
||||
|
DROP TABLE IF EXISTS `user`; |
||||
|
2. DML:增删改表数据 |
||||
|
-- 插入数据(批量插入性能远高于循环单条插入) |
||||
|
INSERT INTO `user` (username, phone, age, gender, balance) |
||||
|
VALUES |
||||
|
('张三', '13800138000', 25, '男', 1000.00), |
||||
|
('李四', '13800138001', 22, '女', 500.00); |
||||
|
-- 更新数据(必须加WHERE条件,否则全表更新!!!) |
||||
|
UPDATE `user` |
||||
|
SET balance = 1500.00, age = 26 |
||||
|
WHERE id = 1; |
||||
|
-- 删除数据(必须加WHERE条件,否则全表删除!!!) |
||||
|
DELETE FROM `user` WHERE id = 1; |
||||
|
-- 清空全表(比DELETE快,自增主键重置) |
||||
|
TRUNCATE TABLE `user`; |
||||
|
3. DQL:数据查询 |
||||
|
-- 语法书写顺序 |
||||
|
SELECT [DISTINCT] 字段列表 |
||||
|
FROM 表名 |
||||
|
[WHERE 条件过滤] |
||||
|
[GROUP BY 分组字段] |
||||
|
[HAVING 分组后过滤] |
||||
|
[ORDER BY 排序字段 ASC/DESC] |
||||
|
[LIMIT 分页偏移量, 条数]; |
||||
|
-- 实际执行顺序 |
||||
|
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT |
||||
|
SELECT u.id, u.username, o.order_no, o.amount |
||||
|
FROM `user` u |
||||
|
INNER JOIN `order` o ON u.id = o.user_id; |
||||
|
-- 查询所有用户,含无订单的用户 |
||||
|
SELECT u.id, u.username, o.order_no, o.amount |
||||
|
FROM `user` u |
||||
|
LEFT JOIN `order` o ON u.id = o.user_id; |
||||
|
|
||||
|
-- 查询无订单的用户 |
||||
|
SELECT u.id, u.username |
||||
|
FROM `user` u |
||||
|
LEFT JOIN `order` o ON u.id = o.user_id |
||||
|
WHERE o.id IS NULL; |
||||
|
-- 创建用户(%允许远程登录,localhost仅本地登录) |
||||
|
CREATE USER 'test_user'@'%' IDENTIFIED BY 'Test@123456'; |
||||
|
|
||||
|
-- 授权(最小权限原则) |
||||
|
GRANT SELECT, INSERT ON test_db.* TO 'test_user'@'%'; -- 给test库授予查询、插入权限 |
||||
|
GRANT ALL PRIVILEGES ON *.* TO 'admin_user'@'%' WITH GRANT OPTION; -- 管理员全权限 |
||||
|
|
||||
|
-- 刷新权限 |
||||
|
FLUSH PRIVILEGES; |
||||
|
|
||||
|
-- 查看权限 |
||||
|
SHOW GRANTS FOR 'test_user'@'%'; |
||||
|
|
||||
|
-- 撤销权限 |
||||
|
REVOKE INSERT ON test_db.* FROM 'test_user'@'%'; |
||||
|
-- 删除用户 |
||||
|
DROP USER 'test_user'@'%'; |
||||
|
五、事务与 ACID、MVCC |
||||
|
1. 事务四大特性(ACID) |
||||
|
事务是一组原子性的 SQL 操作,要么全成功,要么全失败回滚,仅 InnoDB 支持。 |
||||
|
表格 |
||||
|
特性 定义 实现原理 |
||||
|
原子性(Atomicity) 事务是最小执行单元,不可分割,要么全成要么全败 undo log(回滚日志),存储数据历史版本,回滚时恢复 |
||||
|
一致性(Consistency) 事务执行前后,数据的完整性约束不被破坏 事务的最终目的,由原子性、隔离性、持久性共同保证 |
||||
|
隔离性(Isolation) 并发事务之间相互隔离,互不干扰 锁机制 + MVCC 多版本并发控制 |
||||
|
持久性(Durability) 事务提交后,数据修改永久生效,崩溃也不丢失 redo log(重做日志),WAL 预写日志机制 |
||||
|
2. 事务并发问题与隔离级别 |
||||
|
并发问题 |
||||
|
脏读:一个事务读到了另一个事务未提交的数据 |
||||
|
不可重复读:同一事务内,两次读取同一行数据结果不一致(另一个事务修改并提交) |
||||
|
幻读:同一事务内,两次范围查询返回的行数不一致(另一个事务插入 / 删除并提交) |
||||
|
四大隔离级别 |
||||
|
表格 |
||||
|
隔离级别 脏读 不可重复读 幻读 说明 |
||||
|
读未提交(Read Uncommitted) 可能 可能 可能 最低级别,几乎不用 |
||||
|
读已提交(Read Committed) 解决 可能 可能 Oracle、SQL Server 默认 |
||||
|
可重复读(Repeatable Read) 解决 解决 可能(InnoDB 已解决) MySQL 默认级别 |
||||
|
串行化(Serializable) 解决 解决 解决 最高级别,事务串行执行,并发性能极差 |
||||
|
重点:InnoDB 的 RR 级别,通过 ** 临键锁(Next-Key Lock)** 彻底解决了幻读问题。 |
||||
|
3. MVCC 多版本并发控制 |
||||
|
MVCC 是 InnoDB 实现隔离级别的核心,通过数据行的多个版本实现读写不阻塞,大幅提升并发性能。 |
||||
|
核心实现:隐藏字段(DB_TRX_ID、DB_ROLL_PTR)+ undo log + Read View 读视图 |
||||
|
核心逻辑:事务开启时生成 Read View,判断当前事务能看到的数据版本,不同隔离级别 Read View 生成时机不同: |
||||
|
RC 级别:每次 SELECT 都生成新的 Read View,解决脏读 |
||||
|
RR 级别:第一次 SELECT 生成 Read View,后续复用,解决不可重复读 |
||||
|
六、MySQL 锁机制 |
||||
|
锁是实现事务隔离性的核心,解决并发修改数据的冲突问题。 |
||||
|
1. 锁的分类 |
||||
|
按粒度分类 |
||||
|
全局锁:锁住整个实例,所有读写阻塞,仅用于全库备份 |
||||
|
表级锁:锁住整张表,加锁快、冲突概率高、并发差,MyISAM 默认使用 |
||||
|
行级锁:InnoDB 特有,锁住具体行,锁粒度最小、冲突概率最低、并发性能最高 |
||||
|
注意:InnoDB 行锁是针对索引加的锁,查询没用到索引会升级为表锁! |
||||
|
按功能分类 |
||||
|
共享锁(S 锁,读锁):多个事务可同时加 S 锁,阻塞写操作,用法SELECT ... LOCK IN SHARE MODE; |
||||
|
排他锁(X 锁,写锁):一个事务加 X 锁后,其他事务不能加 S/X 锁,读写都阻塞。UPDATE/DELETE/INSERT 会自动加 X 锁,用法SELECT ... FOR UPDATE; |
||||
|
2. InnoDB 行锁 3 种算法(RR 级别) |
||||
|
记录锁:锁住具体的索引记录,如WHERE id=1,仅锁住 id=1 的行 |
||||
|
间隙锁:锁住索引之间的间隙,防止插入数据,解决幻读 |
||||
|
临键锁(Next-Key Lock):记录锁 + 间隙锁,左开右闭区间,InnoDB 默认行锁算法,彻底解决幻读 |
||||
|
3. 死锁 |
||||
|
产生条件:互斥、请求与保持、不剥夺、循环等待 |
||||
|
避免方案: |
||||
|
所有事务按相同顺序访问数据行 |
||||
|
大事务拆分为小事务,减少锁持有时间 |
||||
|
等值查询用唯一索引,避免间隙锁扩大范围 |
||||
|
避免无索引查询导致的表锁 |
||||
@ -0,0 +1,57 @@ |
|||||
|
学习内容:一、核心基础概念 |
||||
|
证券与股票 |
||||
|
证券是经济权益凭证,股票是上市公司发行的股份凭证,属于有价证券。 |
||||
|
证券市场三大功能 |
||||
|
筹资(企业募资、投资者投资)、定价(供求决定资本价格)、资本配置(引导资金流向高回报企业)。 |
||||
|
投资者分类 |
||||
|
分为机构投资者和个人投资者。 |
||||
|
二、股票核心特性 |
||||
|
股票具备风险性、收益性、流通性、波动性、永久性(不退股、可转让)。 |
||||
|
三、股价影响与分析方法 |
||||
|
影响股价因素 |
||||
|
核心是供求关系,还包括公司经营、宏观经济、政策、心理、人为操纵等。 |
||||
|
两大分析流派 |
||||
|
基本面分析:看宏观、行业、公司财务,判断价值。 |
||||
|
技术面分析:看历史走势,遵循市场包容一切、股价沿趋势运行、历史会重演三大公理。 |
||||
|
四、股票交易规则 |
||||
|
交易原则:价格优先、时间优先。 |
||||
|
核心规则 |
||||
|
交易时间:A 股 9:30-11:30、13:00-15:00,含集合竞价。 |
||||
|
交易单位:1 手 = 100 股,零股只能卖出。 |
||||
|
涨跌幅:普通股票单日 ±10%,新股首日除外。 |
||||
|
交收:A 股T+1(次日交割)。 |
||||
|
五、股票与市场分类 |
||||
|
股票类型 |
||||
|
A 股(人民币普通)、B 股(外币计价)、H 股(香港上市)、N/S/T 股(境外上市)。 |
||||
|
市场板块 |
||||
|
主板(大型企业)、中小板(中小盘)、创业板(成长型企业,风险高)、新三板(中小微企业转让平台)。 |
||||
|
六、核心业务与门槛 |
||||
|
融资融券:信用交易(杠杆),个人门槛账户资产≥50 万。 |
||||
|
沪港通:跨境炒股,个人门槛资产≥50 万。 |
||||
|
开户:一人最多可开20 个 A 股账户,本人持身份证、银行卡办理。 |
||||
|
七、交易费用 |
||||
|
主要包含印花税(卖出单边千一)、交易佣金、过户费。 |
||||
|
八、道氏理论(技术分析鼻祖) |
||||
|
市场存在长期(基本运动)、中期(次级运动)、短期(日常波动) 三大趋势,核心是趋势为王、成交量验证趋势、无反转信号则趋势延续。 |
||||
|
九、基础核心术语 |
||||
|
涵盖 K 线、多空、牛熊市、除权 / 除息、市盈率、建仓 / 平仓、套牢、反弹等常用交易名词。 |
||||
|
1. K 线 |
||||
|
记录股价一天涨跌的蜡烛图,红涨绿跌;由实体、上下影线组成,能看开盘 / 收盘 / 最高 / 最低价。 |
||||
|
2. 多空 |
||||
|
多头:看好股价会涨,先买后卖赚差价。 |
||||
|
空头:看跌股价,先借股卖出、跌了再买回还券。 |
||||
|
3. 牛熊市 |
||||
|
牛市:股价长期普遍上涨,多头占优。 |
||||
|
熊市:股价长期普遍下跌,空头占优。 |
||||
|
4. 除权 / 除息 |
||||
|
除息:公司发现金分红,股价扣除分红金额,新股东不再领这笔钱。 |
||||
|
除权:公司送股 / 配股,股本变大,股价按比例下调。 |
||||
|
5. 市盈率(PE) |
||||
|
股价 ÷ 每股盈利,用来衡量股价贵不贵;数值越低,相对越便宜。 |
||||
|
6. 建仓 / 平仓 |
||||
|
建仓:开始买入股票(做多)或卖出(做空)。 |
||||
|
平仓:把手里的持仓卖掉,结束这笔交易。 |
||||
|
7. 套牢 |
||||
|
买完股票就跌、卖完就涨,亏着舍不得卖,被 “套” 在里面。 |
||||
|
8. 反弹 |
||||
|
股价跌了一阵后,短期小幅回升,不是反转大涨。 |
||||
@ -0,0 +1,77 @@ |
|||||
|
GO知识的学习 |
||||
|
Go 程序底层执行流程 |
||||
|
1. 编译器读取 .go 源码 |
||||
|
2. 检查语法错误(package main / main函数 必须存在) |
||||
|
3. 编译为机器码(CPU可直接执行) |
||||
|
4. 从 main() 函数第一行开始执行 |
||||
|
5. 逐行运行代码,执行完毕程序退出 |
||||
|
Go 开发核心注意事项 |
||||
|
可执行程序必须双件套 |
||||
|
只有 package main + func main() 才能运行,缺一不可 |
||||
|
禁止未使用的变量 / 导入包 |
||||
|
短变量 := 有严格限制 |
||||
|
只能在函数内部使用 |
||||
|
同一作用域不能重复声明同一个变量 |
||||
|
全局变量只能用 var,不能用 := |
||||
|
大小写决定访问权限 |
||||
|
大写字母开头:公共(对外可访问,对标 Java public) |
||||
|
小写字母开头:私有(仅包内可访问,对标 Java private) |
||||
|
项目与依赖 |
||||
|
必须用 Go Modules,别碰 GOPATH |
||||
|
所有项目必须执行:go mod init 项目名 |
||||
|
对标 Java 的 Maven/Gradle,管理依赖 |
||||
|
依赖自动清理 |
||||
|
依赖乱了、多了,执行:go mod tidy |
||||
|
自动删无用依赖、补全缺失依赖 |
||||
|
标准库优先,少用第三方包 |
||||
|
Go的转义字符 |
||||
|
\n 换行 输出后换行 |
||||
|
\t 制表符(Tab 空格对齐文本 |
||||
|
\\ 输出一个反斜杠 \ 打印路径 |
||||
|
\" 输出双引号 " 字符串里带引号 |
||||
|
\' 输出单引号 ' 字符里带单引号 |
||||
|
\r 回车(回到行首)\b退格(删除前一个字符) |
||||
|
Go 变量核心知识 |
||||
|
一、变量命名规则 |
||||
|
只能用:字母、数字、下划线 |
||||
|
首字符不能是数字 |
||||
|
区分大小写(name ≠ Name) |
||||
|
不能用 Go 关键字(如 var、func、package) |
||||
|
1. 标准声明(指定类型) |
||||
|
格式:var 变量名 类型 |
||||
|
var name string |
||||
|
var age int |
||||
|
var isOk bool |
||||
|
2. 类型推导(不写类型,Go 自动识别) |
||||
|
格式:var 变量名 = 值 |
||||
|
var name = "张三" // 自动推导为string |
||||
|
var age = 20 // 自动推导为int |
||||
|
var pi = 3.14 // 自动推导为float64 |
||||
|
3. 短变量声明 |
||||
|
格式:变量名 := 值 |
||||
|
func main() { |
||||
|
name := "李四" |
||||
|
age := 25 |
||||
|
fmt.Println(name, age) |
||||
|
} |
||||
|
4. 批量声明(一次声明多个) |
||||
|
// 方式1:var批量 |
||||
|
var a, b, c int |
||||
|
var x, y = 10, "hello" |
||||
|
|
||||
|
// 方式2:批量块(更整洁) |
||||
|
var ( |
||||
|
name string = "王五" |
||||
|
age int = 30 |
||||
|
isStudent bool |
||||
|
) |
||||
|
零值机制 |
||||
|
整型 (int) 0 |
||||
|
浮点型 (float64) 0.0 |
||||
|
字符串 (string) ""(空字符串) |
||||
|
布尔型 (bool) false |
||||
|
:= 只能在函数内用,全局变量禁止用 |
||||
|
变量 / 包定义了必须用,不用直接编译报错 |
||||
|
同一作用域不能重复声明同名变量 |
||||
|
大写开头 = 公共,小写开头 = 私有(和 Java 不同) |
||||
|
短变量 := 至少要声明一个新变量 |
||||
@ -0,0 +1,39 @@ |
|||||
|
超级云脑 - 云脑探秘 功能 |
||||
|
超级云脑 - 云脑探秘是单只股票一站式量化分析工具,以股票检索为入口,从估值、风险、技术位、趋势、主力成本、市场情绪六大维度,提供可视化、通俗化的个股分析结论,帮普通投资者快速看懂个股核心情况。 |
||||
|
1. 股票精准检索(功能入口) |
||||
|
作为全功能的前置操作,支持两种检索方式: |
||||
|
按股票代码精确查找 |
||||
|
按股票名称模糊匹配 |
||||
|
输入后可快速锁定目标上市股票,一键调取该股票专属的全套分析数据,无需复杂筛选,直达标的。 |
||||
|
2. 股票估值(基础价值 + 行情层) |
||||
|
检索出具体股票后,展示两大核心信息: |
||||
|
当前股票估值 |
||||
|
基于市盈率、市净率等核心估值指标,呈现个股当前估值水位(高估 / 合理 / 低估),直观判断估值性价比。 |
||||
|
上一收盘日基础情况 |
||||
|
展示上一交易日关键盘口数据:收盘价、涨跌幅、成交量、成交额、换手率、流通股本等,快速掌握个股昨日收盘的交易活跃度与基础行情。 |
||||
|
3. 安全级别(六色罗盘风险评级) |
||||
|
以六色罗盘为可视化核心,做综合风险判定: |
||||
|
核心依据:结合支撑位有效性、压力位强度、股价所处位置、波动幅度、资金博弈数据 |
||||
|
输出内容:六色罗盘图形 + 明确风险分级(高 / 中 / 低风险、稳健级等) |
||||
|
作用:一眼看懂个股持仓安全等级,快速判断入场 / 持有的整体风险程度。 |
||||
|
4. 压力支撑(关键价位 + 操作指引) |
||||
|
聚焦股价关键攻防点位,提供清晰的阻力 / 支撑判断: |
||||
|
核心数据:精准测算并展示多周期关键价位 |
||||
|
支撑位:短期 / 中期 / 长期强支撑、弱支撑(下跌企稳价位) |
||||
|
压力位:短期 / 中期 / 长期强压力、弱压力(上涨受阻价位) |
||||
|
文字总结:结合当前股价与支撑 / 压力的相对位置,直白说明股价是受支撑企稳、承压回落、突破上攻还是跌破下行,明确多空阻力强弱。 |
||||
|
5. 趋势研判(K 线可视化 + 趋势定性) |
||||
|
从技术走势给出明确方向判断: |
||||
|
可视化展示:呈现个股日 K / 周 K 主流周期 K 线图,搭配均线等辅助指标,清晰呈现走势形态; |
||||
|
趋势总结:基于 K 线形态、量价关系、均线方向,给出确定性趋势结论(如多头上升、空头下跌、横盘震荡、趋势反转 / 延续),直接告知个股当前运行方向与趋势强弱。 |
||||
|
6. 庄家成本(筹码模型 + 主力成本分析) |
||||
|
聚焦主力资金行为,揭秘核心成本: |
||||
|
展示形式:以筹码分布模型可视化呈现,包含筹码峰、筹码集中度、获利盘 / 套牢盘占比等筹码结构数据; |
||||
|
核心分析:基于筹码模型精准算出庄家 / 主力核心成本价格区间,判断筹码密集区、筹码锁定程度与主力控盘力度,帮用户识别主力成本支撑,判断股价下行空间。 |
||||
|
7. 情绪价值(全维度综合总结) |
||||
|
对单只股票做一站式定性总结,整合所有分析维度: |
||||
|
总结内容:涵盖估值高低、风险等级、趋势方向、主力成本状态、市场多空情绪等核心要点; |
||||
|
呈现形式:简短通俗的文字陈述,不堆砌专业术语,直接给出个股整体投资价值与市场情绪导向,让用户快速把握个股全貌。 |
||||
|
整体功能逻辑 |
||||
|
检索股票 → 看估值与基础行情 → 判风险安全等级 → 找压力 / 支撑关键位 → 识股价运行趋势 → 算庄家主力成本 → 得综合情绪与价值结论 |
||||
|
全程可视化、结论化,把专业分析转化为普通投资者易懂的判断依据。 |
||||
@ -0,0 +1,45 @@ |
|||||
|
%v 通用占位符(打印任意类型,默认格式) |
||||
|
%+v 打印结构体时,显示字段名 + 值 |
||||
|
fmt.Printf("%+v", User{"小明"}) {Name:小明} |
||||
|
%#v 打印值的 Go 语法表示(含类型) |
||||
|
%T 打印值的类型 fmt.Printf("类型:%T", 3.14) |
||||
|
%% 打印百分号本身(转义) |
||||
|
%d 十进制整数(int/int64 等) fmt.Printf("数字:%d", 100) 数字:100 |
||||
|
%b 二进制整数 fmt.Printf("二进制:%b", 8) 二进制:1000 |
||||
|
%o 八进制整数 fmt.Printf("八进制:%o", 8) 八进制:10 |
||||
|
%x/%X 十六进制(小写 / 大写) |
||||
|
%f 浮点数(默认保留 6 位小数) |
||||
|
%.2f 浮点数(指定保留 2 位小数) |
||||
|
%e/%E 科学计数法(小写 / 大写) |
||||
|
%U Unicode 编码(如字符转编码) |
||||
|
%s 字符串(直接打印) |
||||
|
%q 字符串带双引号(转义) |
||||
|
%c 单个字符(按 Unicode 打印) |
||||
|
%p 指针地址(十六进制,带 0x)fmt.Printf("指针:%p", &a) |
||||
|
%5d 宽度 5,右对齐(不足补空格) |
||||
|
%-5d 宽度 5,左对齐(不足补空格) |
||||
|
%05d 宽度 5,不足补 0 fmt.Printf("%05d", 123) |
||||
|
%5.2f 总宽度 5,保留 2 位小数(右对齐) |
||||
|
GO的字符串是不可变的,go的数据都有一个默认值没有赋值时Go中不同类型的变量之间赋值时需要显示转换,变量本身没有发生变化基本数据类型转换成string |
||||
|
GO的指针 |
||||
|
核心语法:& 取地址、* 解引用(定义指针 / 访问值); |
||||
|
核心优势:函数传参时修改外部变量、节省内存(大数据传递); |
||||
|
Go 特色:无指针算术、自动 GC、结构体指针可直接用.访问字段(语法糖); |
||||
|
避坑点:空指针(nil)解引用会崩溃,需先判空。 |
||||
|
1. 值类型 |
||||
|
所有基础数据类型 + 结构体 + 数组,都是值类型: |
||||
|
基础类型:int/float/bool/string/byte/rune |
||||
|
复合类型:struct(结构体)、array(数组,如 [5]int) |
||||
|
特殊值类型:int8/int16/uint64 等固定长度数值类型 |
||||
|
2. 引用类型 |
||||
|
只有 3 类核心引用类型(底层封装了指针,Go 帮你简化了指针操作): |
||||
|
slice(切片,如 []int) |
||||
|
map(字典) |
||||
|
chan(通道) |
||||
|
一、标识符的基础规则(语法层面,必须遵守) |
||||
|
这是 Go 编译器强制要求的,违反会直接报错: |
||||
|
字符组成:只能由 字母(a-z/A-Z)、数字(0-9)、下划线(_) 组成; |
||||
|
开头规则:不能以数字开头(如 1score 错误,score1 正确); |
||||
|
大小写敏感:Score 和 score 是两个完全不同的标识符; |
||||
|
不能用关键字:Go 有 25 个关键字(如 if/else/for/struct/var 等),不能作为标识符; |
||||
|
算术运算符,赋值运算符,比较运算符,逻辑运算符,位运算符 |
||||
@ -0,0 +1,66 @@ |
|||||
|
证券定义:证券是经济权益凭证统称,日常所指为有价证券,证券市场是证券发行与交易场所。 |
||||
|
证券市场三大核心功能 |
||||
|
筹资功能:为资金短缺方募资,为盈余方提供投资渠道 |
||||
|
定价功能:由市场供求决定证券(资本)价格 |
||||
|
资本配置功能:引导资本流向高报酬率企业,实现优化配置 |
||||
|
投资者分类:分为机构投资者与个人投资者 |
||||
|
市场发展阶段:荷兰萌芽(1602 年东印度公司)→初步发展→大萧条停滞→二战后恢复→70 年代加速发展 |
||||
|
2. 股票核心基础 |
||||
|
股票定义:上市公司为筹资发行的股份凭证,代表股东权益 |
||||
|
股票五大特性 |
||||
|
风险性:投资存在亏损可能 |
||||
|
收益性:可获公司分红、二级市场差价 |
||||
|
流通性:可在二级市场自由交易变现 |
||||
|
波动性:股价随市场持续波动 |
||||
|
永久性:公司存续期内股票不可退,仅可转让 |
||||
|
股价影响因素:核心是供求关系,其次为公司经营、宏观经济、政策、心理、人为操纵等 |
||||
|
股票分析两大方法 |
||||
|
| 分析类型 | 核心逻辑 | 适用人群 | |
||||
|
| -------- | -------- | -------- | |
||||
|
| 基本面分析 | 价值决定价格,分析宏观、行业、公司财务 | 长期价值投资者 | |
||||
|
| 技术面分析 | 供求决定价格,依据历史走势判断未来 | 个人短期投资者 | |
||||
|
3. 股票交易核心规则 |
||||
|
交易原则:时间优先、价格优先 |
||||
|
交易时间 |
||||
|
A 股:周一至周五 9:30-11:30、13:00-15:00,法定节假日休市 |
||||
|
集合竞价:9:15-9:25(9:20 后不可撤单)、14:57-15:00 |
||||
|
交易单位:100 股 = 1 手,买入需为 1 手整数倍,零股仅可卖出 |
||||
|
涨跌幅限制:非上市首日,普通股票日涨跌幅 **±10%**,委托超限价无效 |
||||
|
4. 市场与股票分类 |
||||
|
股票类型(按上市地 / 计价货币) |
||||
|
A 股:人民币计价,境内上市、国内投资者交易 |
||||
|
B 股:美元 / 港元计价,境内上市、境外投资者交易 |
||||
|
H 股:内地注册、香港上市,港元计价 |
||||
|
N/S/T 股:内地企业在美 / 新 / 日上市 |
||||
|
板块划分 |
||||
|
主板:大型成熟企业,上交所 + 深交所核心市场 |
||||
|
中小板:流通盘约 1 亿以下中小企业,主板过渡 |
||||
|
创业板:成长期创新企业,风险较高,需单独开通权限 |
||||
|
新三板:全国中小企业股份转让系统,服务中小微企业 |
||||
|
5. 交易服务与权限 |
||||
|
证券公司:分经纪商、承销商、自营商、综合类,为投资者提供交易通道 |
||||
|
开户规则:一人最多可开20 个A 股账户 |
||||
|
融资融券 |
||||
|
定义:券商借资买股(融资)、借股卖出(融券)的信用交易 |
||||
|
门槛:个人开户满18 个月、资产≥50 万;机构≥100 万 |
||||
|
沪港通:沪股通 + 港股通,个人参与门槛≥50 万资产 |
||||
|
6. 道氏理论(技术分析鼻祖) |
||||
|
六大核心观点 |
||||
|
平均价格包容消化一切市场因素 |
||||
|
市场存在基本、次级、日常三种趋势 |
||||
|
大趋势分积累、上涨、反转三阶段 |
||||
|
平均价格之间相互验证 |
||||
|
成交量验证趋势方向 |
||||
|
出现明确反转信号才判定趋势终结 |
||||
|
三大趋势 |
||||
|
基本运动:周期≥1 年,涨幅≥30%,牛熊市核心趋势 |
||||
|
次级运动:3 周至数月,为基本运动的回撤 |
||||
|
日常运动:6-10 天,波动无规律、风险极高 |
||||
|
7. 股票交易费用 |
||||
|
表格 |
||||
|
费用类型 收费规则 关键数字 |
||||
|
印花税 单边收取,卖出时征收 成交金额千分之一 |
||||
|
交易佣金 买卖双向收取,券商可协商 默认千分之 1.5 |
||||
|
过户费 变更股权登记收取 深市股票免收 |
||||
|
8. 核心基础名词 |
||||
|
涵盖K 线(阴阳线 / 实体 / 影线)、多空、牛熊市、涨跌停、除权除息、市盈率、市净率、蓝筹股、绩优股等基础术语,是股票交易的基础认知。 |
||||
@ -0,0 +1,116 @@ |
|||||
|
GoFrame 标准结构 |
||||
|
api/ dto 包 + 接口定义 定义前后端交互的接口规范(入参 / 出参) |
||||
|
internal/ src/main/java 核心业务代码(Controller/Service/DAO 全在这) |
||||
|
manifest/ resources/application.yml 项目配置文件(数据库 / 端口 / 环境配置) |
||||
|
resource/ resources/static + templates 静态资源(前端页面 / CSS / 图片) |
||||
|
utility/ utils 工具包 通用工具函数(加密 / 时间 / 字符串处理) |
||||
|
hack/ script 脚本目录 编译 / CI/CD 辅助脚本(非业务代码) |
||||
|
|
||||
|
# 生成名为「gf_demo」的 GoFrame 项目(-u 强制拉取最新模板) |
||||
|
gf init gf_demo -u |
||||
|
数据库go连接 |
||||
|
# 服务端口配置 |
||||
|
server: |
||||
|
address: ":8000" |
||||
|
|
||||
|
# 数据库配置(重点!) |
||||
|
database: |
||||
|
default: |
||||
|
# 连接串格式:mysql:账号:密码@tcp(IP:端口)/数据库名?参数1&参数2 |
||||
|
link: "mysql:root:root@tcp(127.0.0.1:3306)/gf_demo?charset=utf8mb4&parseTime=True&loc=Local" |
||||
|
debug: true # 开启调试,控制台会打印执行的SQL(新手必备) |
||||
|
maxIdle: 10 # 连接池最大空闲连接数 |
||||
|
maxOpen: 100 # 连接池最大活跃连接数 |
||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
// 1. 导入 MySQL 驱动(下划线表示只初始化,不直接调用) |
||||
|
_ "github.com/gogf/gf/v2/contrib/drivers/mysql" |
||||
|
// 2. 导入 GoFrame 核心包 |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gctx" |
||||
|
) |
||||
|
|
||||
|
func main() { |
||||
|
// 初始化上下文(GoFrame 所有操作都需要 ctx) |
||||
|
ctx := gctx.New() |
||||
|
|
||||
|
// 测试数据库连接(核心代码) |
||||
|
testDBConnection(ctx) |
||||
|
|
||||
|
// 启动 GoFrame 服务(Web 项目必备) |
||||
|
g.Server().Run() |
||||
|
} |
||||
|
|
||||
|
// 定义和表对应的结构体(db标签映射数据库字段) |
||||
|
type User struct { |
||||
|
UserName string `json:"user_name" db:"user_name"` |
||||
|
Password string `json:"pwd" db:"pwd"` |
||||
|
Age int `json:"age" db:"age"` |
||||
|
} |
||||
|
|
||||
|
// 新增用户 |
||||
|
func addUser(ctx context.Context) { |
||||
|
db := g.DB() |
||||
|
// Insert():插入数据,支持结构体/Map |
||||
|
result, err := db.Model("user").Ctx(ctx).Insert(User{ |
||||
|
UserName: "小明", |
||||
|
Password: "123456", |
||||
|
Age: 18, |
||||
|
}) |
||||
|
if err != nil { |
||||
|
g.Log().Error(ctx, "新增失败:", err) |
||||
|
return |
||||
|
} |
||||
|
g.Log().Info(ctx, "新增成功,用户ID:", result.LastInsertId()) |
||||
|
} |
||||
|
// 查询所有用户 |
||||
|
func queryUsers(ctx context.Context) { |
||||
|
db := g.DB() |
||||
|
var users []User |
||||
|
// Scan():把查询结果赋值给切片 |
||||
|
err := db.Model("user").Ctx(ctx).Scan(&users) |
||||
|
if err != nil { |
||||
|
g.Log().Error(ctx, "查询失败:", err) |
||||
|
return |
||||
|
} |
||||
|
g.Log().Info(ctx, "查询到用户:", users) |
||||
|
} |
||||
|
// 条件查询(比如查年龄=18的用户) |
||||
|
func queryUserByAge(ctx context.Context) { |
||||
|
db := g.DB() |
||||
|
var user User |
||||
|
// Where():添加查询条件 |
||||
|
err := db.Model("user").Ctx(ctx).Where("age", 18).Scan(&user) |
||||
|
if err != nil { |
||||
|
g.Log().Error(ctx, "条件查询失败:", err) |
||||
|
return |
||||
|
} |
||||
|
g.Log().Info(ctx, "年龄18的用户:", user) |
||||
|
} |
||||
|
// 修改用户年龄 |
||||
|
func updateUser(ctx context.Context) { |
||||
|
db := g.DB() |
||||
|
// Update():修改数据,参数是 Map(键=数据库字段) |
||||
|
result, err := db.Model("user").Ctx(ctx). |
||||
|
Where("user_name", "小明"). // 条件:用户名=小明 |
||||
|
Update(g.Map{"age": 20}) // 修改:年龄=20 |
||||
|
if err != nil { |
||||
|
g.Log().Error(ctx, "修改失败:", err) |
||||
|
return |
||||
|
} |
||||
|
g.Log().Info(ctx, "修改成功,影响行数:", result.RowsAffected()) |
||||
|
} |
||||
|
// 删除用户 |
||||
|
func deleteUser(ctx context.Context) { |
||||
|
db := g.DB() |
||||
|
result, err := db.Model("user").Ctx(ctx). |
||||
|
Where("user_name", "小明"). |
||||
|
Delete() |
||||
|
if err != nil { |
||||
|
g.Log().Error(ctx, "删除失败:", err) |
||||
|
return |
||||
|
} |
||||
|
g.Log().Info(ctx, "删除成功,影响行数:", result.RowsAffected()) |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
股票核心基础术语 |
||||
|
全面梳理股票交易高频术语,涵盖证券、股票、A 股 / B 股 / H 股 / ST 股等标的定义;散户 / 大户 / 庄家 / 主力等投资者分类;基本面 / 政策面 / 技术面、系统 / 非系统风险等分析维度;一级 / 二级市场、牛熊市、多空、T+0/T+1、涨跌停、停牌等市场规则术语;还有送股 / 转增 / 配股、除权除息、北上 / 南下资金、融资融券等实操概念。 |
||||
|
国内证券市场基础 |
||||
|
明确国内仅有沪、深两大证券交易所;按板块划分股票代码规则(创业板 300、沪市 A 股 600/601/603、深市 A 股 000、中小板 002);介绍上证综指、深证成指、中小板 / 创业板指数等核心市场指数。 |
||||
|
股票交易核心规则 |
||||
|
明确交易时间(周一至周五法定假日除外,9:30-11:30、13:00-15:00)、交易单位(1 手 = 100 股)、常规个股 10% 涨跌幅限制、委托可撤单、A 股实行T+1 交收(当日买次日卖)四大核心规则。 |
||||
|
股票交易界面解读 |
||||
|
拆解交易界面核心数据(现价、量比、换手率、委比、内外盘、总市值、市盈率 / 市净率等);讲解分时图、五档买卖盘、成交明细的含义;介绍 K 线图与成交量的基础看法。 |
||||
|
常用技术指标 |
||||
|
讲解 K 线(阴阳线、周期、形态信号)、移动平均线(MA,多头 / 空头排列)、MACD(金叉 / 死叉)、RSI(超买超卖)四大核心技术指标的用法与信号含义。 |
||||
|
股票投资三大派别 |
||||
|
划分价值投资(基本面分析、长线持有)、技术分析(短线交易、看指标趋势)、趋势交易(中长线、介于两者之间)三类主流投资流派。 |
||||
|
After Width: 2268 | Height: 4032 | Size: 2.8 MiB |
|
After Width: 2268 | Height: 4032 | Size: 3.1 MiB |
|
After Width: 2268 | Height: 4032 | Size: 3.0 MiB |
|
After Width: 2268 | Height: 4032 | Size: 3.0 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
@ -0,0 +1,47 @@ |
|||||
|
# 股票相关 |
||||
|
学习了股票相关的常用术语 |
||||
|
#### 投资者相关概念: |
||||
|
散户 大户 庄家 主力 |
||||
|
#### 从股票分析切入点划分: |
||||
|
基本面 政策面 技术面 |
||||
|
#### 市场: |
||||
|
级别: 一级 二级 |
||||
|
趋势: 多头市场 空头市场 |
||||
|
#### 股票类型: |
||||
|
蓝筹股 垃圾股 成长股 龙头股 大盘股 小盘股 |
||||
|
#### 技术词汇: |
||||
|
看多 看空 踏空 跳水 诱多 斩仓 对敲 护盘 洗盘 追涨 杀跌 |
||||
|
天量 地量 天价 地价 持仓量 满仓 空仓 清仓 盘整 反弹 |
||||
|
多头陷阱 空头陷阱 套牢 解套 含息 含权 送股 转增股 配股 |
||||
|
除权 填权 贴权 |
||||
|
|
||||
|
# 技术相关 |
||||
|
### 1.goframe框架的基本结构: |
||||
|
\api - 定义请求和响应 |
||||
|
\hack - 开发时配置文件 |
||||
|
\internal - 项目核心代码 |
||||
|
→\cmd - 项目启动位置,挂载路由 |
||||
|
\consts - 存常量 |
||||
|
\controller - 控制器 |
||||
|
\dao - 数据层 (spring的 mapper) |
||||
|
\logic - 实现层 (spring 的 impl) |
||||
|
\service - 服务层 |
||||
|
\manifest - 部署时需要的配置 |
||||
|
\resource - 资源文件 |
||||
|
\utility - 工具类 |
||||
|
|
||||
|
### 2.路由注册相关 |
||||
|
s:=g.Server() |
||||
|
单独注册 s.BindHandler |
||||
|
分组路由 s.Group(可嵌套) |
||||
|
静态资源绑定路径 s.SetServerRoot |
||||
|
结构体绑定 s.BindObject |
||||
|
单个方法绑定 s.BindObjectMethod |
||||
|
Restful风格 s.BindObjectRest |
||||
|
|
||||
|
### 3.规范路由 |
||||
|
Controller签名格式: func (Example) Execute (ctx context.Context,req *ExampleReq)(res *ExampleReq,err error) |
||||
|
|
||||
|
### 4.非规范路由获取请求参数 |
||||
|
获取请求:g.RequestFromCtx(ctx) |
||||
|
从请求中提取路径参数: request.GetQuery -> 然后用对应数据类型的转换方法提取内部的value属性值 |
||||
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.1 MiB |
@ -0,0 +1,180 @@ |
|||||
|
\# 技术相关: |
||||
|
|
||||
|
\### 获取请求参数剩余部分: |
||||
|
|
||||
|
用map提取参数: .GetQueryMap() .GetQueryMapStrStr .GetQueryMapStrVar |
||||
|
|
||||
|
取Form格式请求体参数: .GetForm()/.GetFormMap() |
||||
|
|
||||
|
获取Restful风格路由参数: GetRouter/GetRouterMap |
||||
|
|
||||
|
一次性取出各类参数: |
||||
|
|
||||
|
Get()=GetRequestMap() |
||||
|
|
||||
|
GetStruct()=GetRequestStruct() (规范路由默认调用) |
||||
|
|
||||
|
|
||||
|
|
||||
|
\### 标签: |
||||
|
|
||||
|
\#### meta标签: |
||||
|
|
||||
|
method: 请求方式(all/get/post...) |
||||
|
|
||||
|
path: 路径 |
||||
|
|
||||
|
sm: 总结 |
||||
|
|
||||
|
tags: 分组标签 |
||||
|
|
||||
|
\#### 普通字段标签: |
||||
|
|
||||
|
dc: 描述 |
||||
|
|
||||
|
p/params: 请求key |
||||
|
|
||||
|
m/orm: 数据库字段名 |
||||
|
|
||||
|
default: 默认值 |
||||
|
|
||||
|
v/vaild: 校验规则 |
||||
|
|
||||
|
ad: 补充说明 |
||||
|
|
||||
|
eg: 示例值 |
||||
|
|
||||
|
|
||||
|
|
||||
|
\### Dao部分 |
||||
|
|
||||
|
\####查询: |
||||
|
|
||||
|
\#####Select |
||||
|
|
||||
|
g.Model("table").One() 查询单条数据 |
||||
|
|
||||
|
g.Model("table").All() 查询全部数据 |
||||
|
|
||||
|
g.Model("table").Feilds()指定字段 |
||||
|
|
||||
|
g.Model("table").FeildsEx()排除字段 |
||||
|
|
||||
|
g.Model("table").Value()查询某一格的内容 |
||||
|
|
||||
|
g.Model("table").Array()查询整列 |
||||
|
|
||||
|
g.Model("table").LockUpdate()申请行级锁 |
||||
|
|
||||
|
\#####聚合函数 |
||||
|
|
||||
|
Count() Sum() Min() Max() Avg() |
||||
|
|
||||
|
\####条件: |
||||
|
|
||||
|
Where() |
||||
|
|
||||
|
WhereLT |
||||
|
|
||||
|
WhereGT |
||||
|
|
||||
|
WhereLTE |
||||
|
|
||||
|
WhereGTE |
||||
|
|
||||
|
WhereIn |
||||
|
|
||||
|
WhereBetween |
||||
|
|
||||
|
WhereNot |
||||
|
|
||||
|
WhereOr.......... |
||||
|
|
||||
|
|
||||
|
|
||||
|
\####排序 |
||||
|
|
||||
|
Order("feild","asc/desc") |
||||
|
|
||||
|
\####分组 |
||||
|
|
||||
|
Group() |
||||
|
|
||||
|
\####分页 |
||||
|
|
||||
|
Limit(origin,offset) |
||||
|
|
||||
|
Page(pageNum,pageCapcity) |
||||
|
|
||||
|
\####扫描为结构体 |
||||
|
|
||||
|
Scan(\&struct) |
||||
|
|
||||
|
\####插入 |
||||
|
|
||||
|
model.Insert()或model.Data().Insert() |
||||
|
|
||||
|
model.Replace() 删除或插入 |
||||
|
|
||||
|
model.Save()更新或插入 |
||||
|
|
||||
|
model.InsertAndGetId()插入并获取自增id |
||||
|
|
||||
|
\####更新 |
||||
|
|
||||
|
Update() |
||||
|
|
||||
|
Increment() |
||||
|
|
||||
|
Decrement() |
||||
|
|
||||
|
\####删除 |
||||
|
|
||||
|
Delete() |
||||
|
|
||||
|
\####时间字段 |
||||
|
|
||||
|
create\_at delete\_at update\_at 增删改时框架自动更新这些字段 |
||||
|
|
||||
|
delete\_at 会被作为逻辑删除的依据 |
||||
|
|
||||
|
\####事务 |
||||
|
|
||||
|
1\.手动管理事务 |
||||
|
|
||||
|
tx,err:=g.DB(),Begin(req.Context())开启事务 |
||||
|
|
||||
|
tx.Rollback()回滚 |
||||
|
|
||||
|
tx.Commit()提交 |
||||
|
|
||||
|
2\.靠抛出error管理的事务 |
||||
|
|
||||
|
err:=g.DB().Transaction(context.TODO(),func(ctx context.Context,tx gbd.Tx)error{}) |
||||
|
|
||||
|
|
||||
|
|
||||
|
\#股票相关: |
||||
|
|
||||
|
|
||||
|
|
||||
|
道氏理论观点: |
||||
|
|
||||
|
平均价格包容消化一切 |
||||
|
|
||||
|
市场同时存在三种趋势(基本运动,次级运动,日常运动) |
||||
|
|
||||
|
大趋势有三个阶段 |
||||
|
|
||||
|
平均价格互相验证 |
||||
|
|
||||
|
成交量验证趋势 |
||||
|
|
||||
|
确切的反转信号判定终结 |
||||
|
|
||||
|
操作口诀:先大后小,先长后短,做熟不做生 |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.1 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
@ -0,0 +1,145 @@ |
|||||
|
# 技术部分 |
||||
|
### 手动编写SQL的方法: |
||||
|
g.DB().Query(ctx,sql,g.Array{}) //查询sql |
||||
|
g.DB().Exec(ctx,sql,g.Array{}) //修改的sql |
||||
|
### Dao代码生成 |
||||
|
config 中需要配置: |
||||
|
gfcli: |
||||
|
gen: |
||||
|
dao: |
||||
|
link: |
||||
|
tables: |
||||
|
执行gf gen dao命令 //即逆向工程 |
||||
|
或直接执行gf gen dao -l "link" -t "tables" 可不用改配置 |
||||
|
|
||||
|
生成代码: |
||||
|
entity包 数据库表对应结构体 |
||||
|
do包 经过包装的结构体,与entity区别是普通字段类型为interface{}而不是基本类型,可用来区分空值和空指针 |
||||
|
dao包 直接隶属dao包的go文件写自定义业务代码,隶属于internal包的go文件用来存储框架预设代码(再次执行gen命令会被覆盖) |
||||
|
|
||||
|
### 级联查询 |
||||
|
#### 一对一关系 |
||||
|
结构体中添加字段: Struct *Struct `orm:"with:id=s_id"` //标签指定关联规则 |
||||
|
查询时使用model.With(entity.Struct{})设置级联的表 |
||||
|
|
||||
|
#### 一对多关系 |
||||
|
结构体中添加字段: Structs []*Struct `orm:"with:id=s_id"` //标签指定关联规则 |
||||
|
|
||||
|
#### 多级级联 |
||||
|
直接在With()中添加多个结构体就行 |
||||
|
|
||||
|
### Service和Logic层 |
||||
|
|
||||
|
根据logic包生成service接口:gf gen service |
||||
|
|
||||
|
#### service |
||||
|
组成部分: |
||||
|
接口 |
||||
|
type IExample interface{ //命名以I开头 |
||||
|
定义业务函数 |
||||
|
} |
||||
|
|
||||
|
定义接口变量 |
||||
|
var localExample() IExample //私有化防止外部修改 |
||||
|
|
||||
|
定义获取接口方法 |
||||
|
func Example () IExample{ |
||||
|
if localExample==nil{ |
||||
|
panic(".....") |
||||
|
} |
||||
|
return localExample |
||||
|
} |
||||
|
|
||||
|
定义注册方法 |
||||
|
func RegisterExample(i IExample){ |
||||
|
localExample=i //用接口实现给接口变量赋值 |
||||
|
} |
||||
|
|
||||
|
#### Logic层 |
||||
|
定义结构体 |
||||
|
type sExample struct{} //以s开头命名 |
||||
|
|
||||
|
初始化方法中注册 |
||||
|
func init(){ |
||||
|
service.RegisterExample(&sExample{}) |
||||
|
} |
||||
|
|
||||
|
实现service的接口中的业务方法 |
||||
|
|
||||
|
#### 初始化接口 |
||||
|
在logic.go中统一import logic,然后再在main.go 中import一次logic.go 实现单例初始化服务接口 |
||||
|
|
||||
|
### 模板输出 |
||||
|
1. req.Response.Writef() //其实就是write套了层Sprintf |
||||
|
2. req.Response.WriteTplContent(string,g.Map{}) //此法是在string中预留{{}}占位符,用g.Map中的value替换占位符 |
||||
|
3. req.Response.WriteTpl(path string, g.Map{}) //此法与上一个区别是第一个参数是HTML文件路径,在文件路径中可以预留占位符进行替换,形式类似于JSP或Thymeleaf |
||||
|
4. 模板中的流程控制语句: |
||||
|
条件判断 |
||||
|
{{if [compare] variable1 variable2}} |
||||
|
{{else}} |
||||
|
{{end}} |
||||
|
循环遍历切片 |
||||
|
{{range.slice}} |
||||
|
{{end}} |
||||
|
循环遍历map |
||||
|
{{range $key,$value := .map}} |
||||
|
{{end}} |
||||
|
|
||||
|
### 文件上传 |
||||
|
file:=req.GetUploadFile("name") |
||||
|
规范路由写法: |
||||
|
属性: File *ghttp.UploadFile `p:"name"` |
||||
|
全局配置文件大小限制: |
||||
|
config文件中 |
||||
|
server: |
||||
|
clientMaxBodySize: "" |
||||
|
|
||||
|
局部配置文件大小限制: |
||||
|
标签:v:"max-size: xxx MB" |
||||
|
|
||||
|
### 文件下载 |
||||
|
req.Response.ServerFile("/path") // 图片会显示在前端而不主动下载 |
||||
|
req.Response.ServerFileDownload("/path","name") //无论是不是图片都会立刻开始下载 |
||||
|
|
||||
|
### Cookie和Session |
||||
|
req.Cookie.Set("key","value") |
||||
|
req.Cookie.SetCookie// 有多项设置,自由度较高 |
||||
|
req.Cookie.Remove("key") //移除cookie |
||||
|
req.Session.Set("key","value") |
||||
|
req.Session.Remove("key") |
||||
|
|
||||
|
### 时间工具 |
||||
|
gtime.Now() Date() DateTime() New() Format() TimeStamp().... |
||||
|
|
||||
|
### 随机工具 |
||||
|
grand.Intn() grand.N() grand.S() grand.Letters()..... |
||||
|
|
||||
|
### 中间件 |
||||
|
固定签名格式: |
||||
|
func 函数名 (r *ghttp.Request){ |
||||
|
前置中间件业务逻辑 |
||||
|
r.Middleware.Next() |
||||
|
后置中间件业务逻辑 |
||||
|
} |
||||
|
挂载方法: |
||||
|
1.全局中间件 2.分组路由中间件 |
||||
|
|
||||
|
|
||||
|
|
||||
|
# 业务部分 |
||||
|
|
||||
|
## 超级云脑-云脑探秘 功能总结 |
||||
|
|
||||
|
首先是可以根据股票代码或名称搜索股票 |
||||
|
#### 股票估值 |
||||
|
搜索出具体的股票后,显示当前股票估值和上一收盘日的基本情况 |
||||
|
#### 安全级别 |
||||
|
显示六色罗盘,分析支撑和压力情况,据此显示风险分级 |
||||
|
#### 压力支撑 |
||||
|
显示支撑位和压力位,根据支撑压力数据显示简短的总结 |
||||
|
#### 趋势研判 |
||||
|
显示K线图,并总结趋势 |
||||
|
#### 庄家成本 |
||||
|
显示筹码模型,根据筹码模型分析陈本价格 |
||||
|
#### 情绪价值 |
||||
|
对该支股票进行简短的总结陈述 |
||||
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.3 MiB |
|
After Width: 1080 | Height: 1920 | Size: 1.2 MiB |
@ -0,0 +1,116 @@ |
|||||
|
## 技术方面 |
||||
|
|
||||
|
### 打包指令 |
||||
|
|
||||
|
配置: |
||||
|
|
||||
|
```yaml |
||||
|
gfcli: |
||||
|
build: |
||||
|
name: "" |
||||
|
arch: "amd64" # 配置CPU架构 |
||||
|
system: "linux,darwin,windows" # 配置操作系统 |
||||
|
mod: "" #GoModules编译模式,默认留空 |
||||
|
cgo:0 # 是否允许调用C代码,0禁用1启用 |
||||
|
packSrc: "manifest,resource" # 指定一起打包的静态资源路径 |
||||
|
``` |
||||
|
|
||||
|
命令: gf build |
||||
|
|
||||
|
|
||||
|
|
||||
|
### Bcrypt加密 |
||||
|
|
||||
|
```go |
||||
|
//加密: |
||||
|
bcrypt.GenerateFromPassword([]byte("要加密的内容"),int 加密次数2^int次) |
||||
|
|
||||
|
//验证: |
||||
|
err:=bcrypt.CompareHashAndPassword(hash,password) |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
|
||||
|
### JWT |
||||
|
|
||||
|
#### golang-jwt |
||||
|
|
||||
|
```go |
||||
|
//1.定义结构体 |
||||
|
type MyClaims struct{ |
||||
|
ID uint |
||||
|
Username string |
||||
|
jwt.RegisteredClaims |
||||
|
} |
||||
|
|
||||
|
//2.签发 |
||||
|
claims:=MyClaims{ |
||||
|
.... |
||||
|
RegisteredClaims: jwt.RegisteredClaims{ |
||||
|
设置token参数,如过期时间等 |
||||
|
} |
||||
|
} |
||||
|
token:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims) |
||||
|
token =token.SignedString([]byte(密钥)) |
||||
|
|
||||
|
//3.验签 |
||||
|
token,err:= jwt.ParseWithClaims(tokenString, &model.MyClaim{}, func(token *jwt.Token) (interface{}, error) { |
||||
|
_, ok := token.Method.(*jwt.SigningMethodHMAC) //验证加密方式 |
||||
|
if !ok { |
||||
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) |
||||
|
} |
||||
|
return []byte(密钥), nil |
||||
|
}) |
||||
|
if err!=nil {return nil,err} |
||||
|
|
||||
|
if claims,ok:=token.Claims.(*MyClaims);ok&&token.Valid{ |
||||
|
return claims,nil |
||||
|
} |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
#### gf-jwt |
||||
|
|
||||
|
gf-jwt是以中间件的形式管理token |
||||
|
|
||||
|
```go |
||||
|
//1.初始化中间件 |
||||
|
var Auth:=&gfjwt.GFJWTMiddleware{ |
||||
|
Realm:"name", |
||||
|
Key:[]byte(密钥), |
||||
|
Timeout:过期时间, |
||||
|
MaxRefresh: token刷新窗口期 |
||||
|
IdentityKey: "id" //payload中标识身份的key |
||||
|
Authenticator:func(r *ghttp.Request)(interface{},error)//回调函数,处理登录验签逻辑 |
||||
|
} |
||||
|
//2.注册中间件 |
||||
|
//3.从token中获取数据 |
||||
|
_,data:=Auth.GetIdentity(g.RequestFromCtx(ctx)) |
||||
|
userId:=gconv.Uint64(data(g.Map)["id"]) |
||||
|
|
||||
|
|
||||
|
``` |
||||
|
|
||||
|
|
||||
|
|
||||
|
## 夺宝奇兵功能 |
||||
|
|
||||
|
### 机构动向 |
||||
|
|
||||
|
#### --股票估值-- |
||||
|
|
||||
|
显示股票当前或上一次收盘的基本信息 |
||||
|
|
||||
|
### --当日资金-- |
||||
|
|
||||
|
分析资金流入流出方向,列出了主力资金状况、主力吸筹有无、庄散对决情况 |
||||
|
|
||||
|
|
||||
|
|
||||
|
### AI 预测大模型--股价预测 |
||||
|
|
||||
|
展示7项数据:现价、卖出价、买回价,预测高一高二、低一低二 |
||||
|
|
||||
|
展示K线图 |
||||
|
|
||||
|
功能亮点介绍 |
||||
@ -0,0 +1 @@ |
|||||
|
* linguist-language=GO |
||||
@ -0,0 +1,19 @@ |
|||||
|
.buildpath |
||||
|
.hgignore.swp |
||||
|
.project |
||||
|
.orig |
||||
|
.swp |
||||
|
.idea/ |
||||
|
.settings/ |
||||
|
.vscode/ |
||||
|
bin/ |
||||
|
**/.DS_Store |
||||
|
gf |
||||
|
main |
||||
|
main.exe |
||||
|
output/ |
||||
|
manifest/output/ |
||||
|
temp/ |
||||
|
temp.yaml |
||||
|
bin |
||||
|
**/config/config.yaml |
||||
@ -0,0 +1,7 @@ |
|||||
|
ROOT_DIR = $(shell pwd) |
||||
|
NAMESPACE = "default" |
||||
|
DEPLOY_NAME = "template-single" |
||||
|
DOCKER_NAME = "template-single" |
||||
|
|
||||
|
include ./hack/hack-cli.mk |
||||
|
include ./hack/hack.mk |
||||
@ -0,0 +1,6 @@ |
|||||
|
# GoFrame Template For SingleRepo |
||||
|
|
||||
|
Quick Start: |
||||
|
- https://goframe.org/quick |
||||
|
|
||||
|
没做规范化处理目前!! |
||||
@ -0,0 +1,57 @@ |
|||||
|
package user |
||||
|
|
||||
|
import ( |
||||
|
"gf_demo_02/internal/model/entity" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
type LoginReq struct { |
||||
|
g.Meta `path:"/login" method:"post"` |
||||
|
Username string |
||||
|
Password string |
||||
|
} |
||||
|
|
||||
|
type LoginRes struct { |
||||
|
Token string `json:"token"` //token加签后的字符串
|
||||
|
} |
||||
|
|
||||
|
type GetUserListReq struct { |
||||
|
g.Meta `path:"/getUsers" method:"get"` |
||||
|
} |
||||
|
|
||||
|
type GetUserListRes struct { |
||||
|
Users []entity.User `json:"users"` |
||||
|
} |
||||
|
|
||||
|
type EditUserReq struct { |
||||
|
g.Meta `path:"/admin/user/editUser" method:"post"` |
||||
|
Id uint `json:"id"` |
||||
|
Name string `json:"name" v:"required"` |
||||
|
Property uint `json:"property" v:"between:1,5 #权限必须为1-5"` |
||||
|
Pass string `json:"pass"` |
||||
|
} |
||||
|
|
||||
|
type EditUserRes struct { |
||||
|
} |
||||
|
|
||||
|
type DeleteUserReq struct { |
||||
|
g.Meta `path:"/admin/user/delete" method:"delete"` |
||||
|
Id uint `json:"id" v:"required#缺少用户id"` |
||||
|
} |
||||
|
type DeleteUserRes struct{} |
||||
|
|
||||
|
type GetSelfReq struct { |
||||
|
g.Meta `path:"/admin/user/getSelf" method:"get"` |
||||
|
} |
||||
|
type GetSelfRes struct { |
||||
|
User entity.User `json:"user"` |
||||
|
} |
||||
|
|
||||
|
type SearchUserReq struct { |
||||
|
g.Meta `path:"/admin/user/search" method:"get"` |
||||
|
Keyword string `json:"keyword" p:"keyword"` |
||||
|
} |
||||
|
|
||||
|
type SearchUserRes struct { |
||||
|
Users []entity.User `json:"users"` |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
module gf_demo_02 |
||||
|
|
||||
|
go 1.21 |
||||
|
|
||||
|
toolchain go1.21.13 |
||||
|
|
||||
|
require ( |
||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible |
||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0 |
||||
|
github.com/gogf/gf/v2 v2.7.0 |
||||
|
github.com/golang-jwt/jwt/v5 v5.3.1 |
||||
|
golang.org/x/crypto v0.21.0 |
||||
|
) |
||||
|
|
||||
|
require ( |
||||
|
github.com/BurntSushi/toml v1.3.2 // indirect |
||||
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect |
||||
|
github.com/fatih/color v1.16.0 // indirect |
||||
|
github.com/fsnotify/fsnotify v1.7.0 // indirect |
||||
|
github.com/go-logr/logr v1.2.4 // indirect |
||||
|
github.com/go-logr/stdr v1.2.2 // indirect |
||||
|
github.com/go-sql-driver/mysql v1.7.1 // indirect |
||||
|
github.com/gorilla/websocket v1.5.1 // indirect |
||||
|
github.com/grokify/html-strip-tags-go v0.1.0 // indirect |
||||
|
github.com/magiconair/properties v1.8.7 // indirect |
||||
|
github.com/mattn/go-colorable v0.1.13 // indirect |
||||
|
github.com/mattn/go-isatty v0.0.20 // indirect |
||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect |
||||
|
github.com/olekukonko/tablewriter v0.0.5 // indirect |
||||
|
github.com/rivo/uniseg v0.4.4 // indirect |
||||
|
go.opentelemetry.io/otel v1.14.0 // indirect |
||||
|
go.opentelemetry.io/otel/sdk v1.14.0 // indirect |
||||
|
go.opentelemetry.io/otel/trace v1.14.0 // indirect |
||||
|
golang.org/x/net v0.23.0 // indirect |
||||
|
golang.org/x/sys v0.19.0 // indirect |
||||
|
golang.org/x/text v0.14.0 // indirect |
||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect |
||||
|
) |
||||
@ -0,0 +1,70 @@ |
|||||
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= |
||||
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= |
||||
|
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= |
||||
|
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= |
||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= |
||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= |
||||
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= |
||||
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= |
||||
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= |
||||
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= |
||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= |
||||
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= |
||||
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= |
||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= |
||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= |
||||
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= |
||||
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= |
||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0 h1:5Igvtz4gy5UMvH+Ut4kLIpwSzggV9ZgDVBsIiOctH5E= |
||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0/go.mod h1:0+flZ0clMKjtH1sTI7YD2KG4FPr8xz0L9h1WMd5M2Z8= |
||||
|
github.com/gogf/gf/v2 v2.7.0 h1:CjxhbMiE7oqf6K8ZtGuKt3dQEwK4vL6LhiI+dI7tJGU= |
||||
|
github.com/gogf/gf/v2 v2.7.0/go.mod h1:Qu8nimKt9aupJQcdUL85tWF4Mfxocz97zUt8UC4abVI= |
||||
|
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= |
||||
|
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= |
||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= |
||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= |
||||
|
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= |
||||
|
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= |
||||
|
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= |
||||
|
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= |
||||
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= |
||||
|
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= |
||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= |
||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= |
||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= |
||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= |
||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= |
||||
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= |
||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= |
||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= |
||||
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= |
||||
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= |
||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= |
||||
|
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= |
||||
|
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= |
||||
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= |
||||
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= |
||||
|
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= |
||||
|
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= |
||||
|
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= |
||||
|
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= |
||||
|
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= |
||||
|
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= |
||||
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= |
||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= |
||||
|
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= |
||||
|
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= |
||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
||||
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= |
||||
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= |
||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= |
||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |
||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
||||
@ -0,0 +1,13 @@ |
|||||
|
|
||||
|
# CLI tool, only in development environment. |
||||
|
# https://goframe.org/docs/cli |
||||
|
gfcli: |
||||
|
gen: |
||||
|
dao: |
||||
|
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" |
||||
|
descriptionTag: true |
||||
|
|
||||
|
docker: |
||||
|
build: "-a amd64 -s linux -p temp -ew" |
||||
|
tagPrefixes: |
||||
|
- my.image.pub/my-app |
||||
@ -0,0 +1,20 @@ |
|||||
|
|
||||
|
# Install/Update to the latest CLI tool.
|
||||
|
.PHONY: cli |
||||
|
cli: |
||||
|
@set -e; \
|
||||
|
wget -O gf \
|
||||
|
https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \
|
||||
|
chmod +x gf && \
|
||||
|
./gf install -y && \
|
||||
|
rm ./gf |
||||
|
|
||||
|
|
||||
|
# Check and install CLI tool.
|
||||
|
.PHONY: cli.install |
||||
|
cli.install: |
||||
|
@set -e; \
|
||||
|
gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \
|
||||
|
echo "GoFame CLI is not installed, start proceeding auto installation..."; \
|
||||
|
make cli; \
|
||||
|
fi; |
||||
@ -0,0 +1,75 @@ |
|||||
|
.DEFAULT_GOAL := build |
||||
|
|
||||
|
# Update GoFrame and its CLI to latest stable version.
|
||||
|
.PHONY: up |
||||
|
up: cli.install |
||||
|
@gf up -a |
||||
|
|
||||
|
# Build binary using configuration from hack/config.yaml.
|
||||
|
.PHONY: build |
||||
|
build: cli.install |
||||
|
@gf build -ew |
||||
|
|
||||
|
# Parse api and generate controller/sdk.
|
||||
|
.PHONY: ctrl |
||||
|
ctrl: cli.install |
||||
|
@gf gen ctrl |
||||
|
|
||||
|
# Generate Go files for DAO/DO/Entity.
|
||||
|
.PHONY: dao |
||||
|
dao: cli.install |
||||
|
@gf gen dao |
||||
|
|
||||
|
# Parse current project go files and generate enums go file.
|
||||
|
.PHONY: enums |
||||
|
enums: cli.install |
||||
|
@gf gen enums |
||||
|
|
||||
|
# Generate Go files for Service.
|
||||
|
.PHONY: service |
||||
|
service: cli.install |
||||
|
@gf gen service |
||||
|
|
||||
|
|
||||
|
# Build docker image.
|
||||
|
.PHONY: image |
||||
|
image: cli.install |
||||
|
$(eval _TAG = $(shell git rev-parse --short HEAD)) |
||||
|
ifneq (, $(shell git status --porcelain 2>/dev/null)) |
||||
|
$(eval _TAG = $(_TAG).dirty) |
||||
|
endif |
||||
|
$(eval _TAG = $(if ${TAG}, ${TAG}, $(_TAG))) |
||||
|
$(eval _PUSH = $(if ${PUSH}, ${PUSH}, )) |
||||
|
@gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG}; |
||||
|
|
||||
|
|
||||
|
# Build docker image and automatically push to docker repo.
|
||||
|
.PHONY: image.push |
||||
|
image.push: cli.install |
||||
|
@make image PUSH=-p; |
||||
|
|
||||
|
|
||||
|
# Deploy image and yaml to current kubectl environment.
|
||||
|
.PHONY: deploy |
||||
|
deploy: cli.install |
||||
|
$(eval _TAG = $(if ${TAG}, ${TAG}, develop)) |
||||
|
|
||||
|
@set -e; \
|
||||
|
mkdir -p $(ROOT_DIR)/temp/kustomize;\
|
||||
|
cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\
|
||||
|
kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\
|
||||
|
kubectl apply -f $(ROOT_DIR)/temp/kustomize.yaml; \
|
||||
|
if [ $(DEPLOY_NAME) != "" ]; then \
|
||||
|
kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \
|
||||
|
fi; |
||||
|
|
||||
|
|
||||
|
# Parsing protobuf files and generating go files.
|
||||
|
.PHONY: pb |
||||
|
pb: cli.install |
||||
|
@gf gen pb |
||||
|
|
||||
|
# Generate protobuf files for database tables.
|
||||
|
.PHONY: pbentity |
||||
|
pbentity: cli.install |
||||
|
@gf gen pbentity |
||||
@ -0,0 +1,30 @@ |
|||||
|
package cmd |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"gf_demo_02/internal/controller/user" |
||||
|
"gf_demo_02/internal/service" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
"github.com/gogf/gf/v2/os/gcmd" |
||||
|
) |
||||
|
|
||||
|
var ( |
||||
|
Main = gcmd.Command{ |
||||
|
Name: "main", |
||||
|
Usage: "main", |
||||
|
Brief: "start http server", |
||||
|
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { |
||||
|
s := g.Server() |
||||
|
s.Group("/", func(group *ghttp.RouterGroup) { |
||||
|
group.Middleware(service.CorsMiddleware) |
||||
|
group.Middleware(ghttp.MiddlewareHandlerResponse) |
||||
|
group.Middleware(service.JWTMiddleware) |
||||
|
group.Bind(user.CUser{}) |
||||
|
}) |
||||
|
s.Run() |
||||
|
return nil |
||||
|
}, |
||||
|
} |
||||
|
) |
||||
@ -0,0 +1,3 @@ |
|||||
|
package consts |
||||
|
|
||||
|
const TOKEN_KEY = "55558888" |
||||
@ -0,0 +1,98 @@ |
|||||
|
package user |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"gf_demo_02/api/user/v1" |
||||
|
"gf_demo_02/internal/consts" |
||||
|
m "gf_demo_02/internal/model" |
||||
|
"gf_demo_02/internal/model/entity" |
||||
|
"gf_demo_02/internal/service" |
||||
|
"github.com/gogf/gf/v2/errors/gcode" |
||||
|
"github.com/gogf/gf/v2/errors/gerror" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
jwt "github.com/golang-jwt/jwt/v5" |
||||
|
"golang.org/x/crypto/bcrypt" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
type CUser struct{} |
||||
|
|
||||
|
func (*CUser) Login(ctx context.Context, req *user.LoginReq) (res *user.LoginRes, err error) { |
||||
|
model := g.DB().Model("user") |
||||
|
u := new(entity.User) |
||||
|
res = new(user.LoginRes) |
||||
|
err = model.Where("name", req.Username).Scan(&u) |
||||
|
if err != nil || u.Id == 0 { |
||||
|
return nil, gerror.NewCode(gcode.New(451, "用户名不存在", nil), "用户名不存在") |
||||
|
} |
||||
|
if bcrypt.CompareHashAndPassword([]byte(u.Pass), []byte(req.Password)) != nil { |
||||
|
return nil, gerror.NewCode(gcode.New(450, "密码错误", nil), "密码错误") |
||||
|
} |
||||
|
claims := m.UserClaim{ |
||||
|
UserId: u.Id, |
||||
|
UserName: u.Name, |
||||
|
RegisteredClaims: jwt.RegisteredClaims{ |
||||
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), |
||||
|
IssuedAt: jwt.NewNumericDate(time.Now()), |
||||
|
NotBefore: jwt.NewNumericDate(time.Now()), |
||||
|
Issuer: "我"}, |
||||
|
} |
||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) |
||||
|
tokenStr, err := token.SignedString([]byte(consts.TOKEN_KEY)) |
||||
|
res.Token = tokenStr |
||||
|
return res, nil |
||||
|
} |
||||
|
|
||||
|
func (*CUser) GetUserList(ctx context.Context, req *user.GetUserListReq) (res *user.GetUserListRes, err error) { |
||||
|
users, err := service.User().GetUserList(ctx) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
res = new(user.GetUserListRes) |
||||
|
res.Users = users |
||||
|
return res, nil |
||||
|
} |
||||
|
|
||||
|
func (*CUser) EditUser(ctx context.Context, req *user.EditUserReq) (res *user.EditUserRes, err error) { |
||||
|
res = new(user.EditUserRes) |
||||
|
if req.Id == 0 { |
||||
|
err = service.User().AddUser(ctx, req) |
||||
|
} else { |
||||
|
err = service.User().UpdateUser(ctx, req) |
||||
|
} |
||||
|
if err != nil { |
||||
|
return res, err |
||||
|
} |
||||
|
return res, nil |
||||
|
} |
||||
|
|
||||
|
func (*CUser) DeleteUser(ctx context.Context, req *user.DeleteUserReq) (res *user.DeleteUserRes, err error) { |
||||
|
return nil, service.User().DeleteUser(ctx, req) |
||||
|
} |
||||
|
|
||||
|
func (*CUser) GetSelf(ctx context.Context, req *user.GetSelfReq) (res *user.GetSelfRes, err error) { |
||||
|
r := g.RequestFromCtx(ctx) |
||||
|
u := r.GetCtxVar("user") |
||||
|
res = new(user.GetSelfRes) |
||||
|
err = u.Struct(&res.User) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return res, nil |
||||
|
} |
||||
|
|
||||
|
func (*CUser) SearchUser(ctx context.Context, req *user.SearchUserReq) (res *user.SearchUserRes, err error) { |
||||
|
res = new(user.SearchUserRes) |
||||
|
if g.IsEmpty(req.Keyword) { |
||||
|
res.Users, err = service.User().GetUserList(ctx) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return res, nil |
||||
|
} |
||||
|
res.Users, err = service.User().SearchUser(ctx, req.Keyword) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return res, nil |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"gf_demo_02/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalCourseDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalCourseDao = *internal.CourseDao |
||||
|
|
||||
|
// courseDao is the data access object for table course.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type courseDao struct { |
||||
|
internalCourseDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// Course is globally public accessible object for table course operations.
|
||||
|
Course = courseDao{ |
||||
|
internal.NewCourseDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,83 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// CourseDao is the data access object for table course.
|
||||
|
type CourseDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns CourseColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// CourseColumns defines and stores column names for table course.
|
||||
|
type CourseColumns struct { |
||||
|
Id string //
|
||||
|
Name string //
|
||||
|
Day string //
|
||||
|
CreateAt string //
|
||||
|
UpdateAt string //
|
||||
|
DeleteAt string //
|
||||
|
} |
||||
|
|
||||
|
// courseColumns holds the columns for table course.
|
||||
|
var courseColumns = CourseColumns{ |
||||
|
Id: "id", |
||||
|
Name: "name", |
||||
|
Day: "day", |
||||
|
CreateAt: "create_at", |
||||
|
UpdateAt: "update_at", |
||||
|
DeleteAt: "delete_at", |
||||
|
} |
||||
|
|
||||
|
// NewCourseDao creates and returns a new DAO object for table data access.
|
||||
|
func NewCourseDao() *CourseDao { |
||||
|
return &CourseDao{ |
||||
|
group: "default", |
||||
|
table: "course", |
||||
|
columns: courseColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *CourseDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *CourseDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *CourseDao) Columns() CourseColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *CourseDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *CourseDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *CourseDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// StockDao is the data access object for table stock.
|
||||
|
type StockDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns StockColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// StockColumns defines and stores column names for table stock.
|
||||
|
type StockColumns struct { |
||||
|
Id string //
|
||||
|
Name string //
|
||||
|
Num string //
|
||||
|
CreateAt string //
|
||||
|
UpdateAt string //
|
||||
|
DeleteAt string //
|
||||
|
} |
||||
|
|
||||
|
// stockColumns holds the columns for table stock.
|
||||
|
var stockColumns = StockColumns{ |
||||
|
Id: "id", |
||||
|
Name: "name", |
||||
|
Num: "num", |
||||
|
CreateAt: "create_at", |
||||
|
UpdateAt: "update_at", |
||||
|
DeleteAt: "delete_at", |
||||
|
} |
||||
|
|
||||
|
// NewStockDao creates and returns a new DAO object for table data access.
|
||||
|
func NewStockDao() *StockDao { |
||||
|
return &StockDao{ |
||||
|
group: "default", |
||||
|
table: "stock", |
||||
|
columns: stockColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *StockDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *StockDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *StockDao) Columns() StockColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *StockDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *StockDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *StockDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// UserDao is the data access object for table user.
|
||||
|
type UserDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns UserColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// UserColumns defines and stores column names for table user.
|
||||
|
type UserColumns struct { |
||||
|
Id string //
|
||||
|
Name string //
|
||||
|
Pass string //
|
||||
|
Property string //
|
||||
|
CreateAt string //
|
||||
|
DeleteAt string //
|
||||
|
UpdateAt string //
|
||||
|
} |
||||
|
|
||||
|
// userColumns holds the columns for table user.
|
||||
|
var userColumns = UserColumns{ |
||||
|
Id: "id", |
||||
|
Name: "name", |
||||
|
Pass: "pass", |
||||
|
Property: "property", |
||||
|
CreateAt: "create_at", |
||||
|
DeleteAt: "delete_at", |
||||
|
UpdateAt: "update_at", |
||||
|
} |
||||
|
|
||||
|
// NewUserDao creates and returns a new DAO object for table data access.
|
||||
|
func NewUserDao() *UserDao { |
||||
|
return &UserDao{ |
||||
|
group: "default", |
||||
|
table: "user", |
||||
|
columns: userColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *UserDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *UserDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *UserDao) Columns() UserColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *UserDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *UserDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *UserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,75 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package internal |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// UserCourseDao is the data access object for table user_course.
|
||||
|
type UserCourseDao struct { |
||||
|
table string // table is the underlying table name of the DAO.
|
||||
|
group string // group is the database configuration group name of current DAO.
|
||||
|
columns UserCourseColumns // columns contains all the column names of Table for convenient usage.
|
||||
|
} |
||||
|
|
||||
|
// UserCourseColumns defines and stores column names for table user_course.
|
||||
|
type UserCourseColumns struct { |
||||
|
Uid string //
|
||||
|
Cid string //
|
||||
|
} |
||||
|
|
||||
|
// userCourseColumns holds the columns for table user_course.
|
||||
|
var userCourseColumns = UserCourseColumns{ |
||||
|
Uid: "uid", |
||||
|
Cid: "cid", |
||||
|
} |
||||
|
|
||||
|
// NewUserCourseDao creates and returns a new DAO object for table data access.
|
||||
|
func NewUserCourseDao() *UserCourseDao { |
||||
|
return &UserCourseDao{ |
||||
|
group: "default", |
||||
|
table: "user_course", |
||||
|
columns: userCourseColumns, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
|
func (dao *UserCourseDao) DB() gdb.DB { |
||||
|
return g.DB(dao.group) |
||||
|
} |
||||
|
|
||||
|
// Table returns the table name of current dao.
|
||||
|
func (dao *UserCourseDao) Table() string { |
||||
|
return dao.table |
||||
|
} |
||||
|
|
||||
|
// Columns returns all column names of current dao.
|
||||
|
func (dao *UserCourseDao) Columns() UserCourseColumns { |
||||
|
return dao.columns |
||||
|
} |
||||
|
|
||||
|
// Group returns the configuration group name of database of current dao.
|
||||
|
func (dao *UserCourseDao) Group() string { |
||||
|
return dao.group |
||||
|
} |
||||
|
|
||||
|
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
|
func (dao *UserCourseDao) Ctx(ctx context.Context) *gdb.Model { |
||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx) |
||||
|
} |
||||
|
|
||||
|
// Transaction wraps the transaction logic using function f.
|
||||
|
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||
|
//
|
||||
|
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
|
// as it is automatically handled by this function.
|
||||
|
func (dao *UserCourseDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { |
||||
|
return dao.Ctx(ctx).Transaction(ctx, f) |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"gf_demo_02/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalStockDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalStockDao = *internal.StockDao |
||||
|
|
||||
|
// stockDao is the data access object for table stock.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type stockDao struct { |
||||
|
internalStockDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// Stock is globally public accessible object for table stock operations.
|
||||
|
Stock = stockDao{ |
||||
|
internal.NewStockDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"gf_demo_02/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalUserDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalUserDao = *internal.UserDao |
||||
|
|
||||
|
// userDao is the data access object for table user.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type userDao struct { |
||||
|
internalUserDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// User is globally public accessible object for table user operations.
|
||||
|
User = userDao{ |
||||
|
internal.NewUserDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,27 @@ |
|||||
|
// =================================================================================
|
||||
|
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package dao |
||||
|
|
||||
|
import ( |
||||
|
"gf_demo_02/internal/dao/internal" |
||||
|
) |
||||
|
|
||||
|
// internalUserCourseDao is internal type for wrapping internal DAO implements.
|
||||
|
type internalUserCourseDao = *internal.UserCourseDao |
||||
|
|
||||
|
// userCourseDao is the data access object for table user_course.
|
||||
|
// You can define custom methods on it to extend its functionality as you wish.
|
||||
|
type userCourseDao struct { |
||||
|
internalUserCourseDao |
||||
|
} |
||||
|
|
||||
|
var ( |
||||
|
// UserCourse is globally public accessible object for table user_course operations.
|
||||
|
UserCourse = userCourseDao{ |
||||
|
internal.NewUserCourseDao(), |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// Fill with you ideas below.
|
||||
@ -0,0 +1,12 @@ |
|||||
|
package course |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"gf_demo_02/internal/model" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
func GetCourses(ctx context.Context) (courses []model.CourseWithUsers, err error) { |
||||
|
g.Redis().HGetAll() |
||||
|
g.Dump() |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
package logic |
||||
|
|
||||
|
import ( |
||||
|
_ "gf_demo_02/internal/logic/user" |
||||
|
) |
||||
@ -0,0 +1,143 @@ |
|||||
|
package user |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"gf_demo_02/api/user/v1" |
||||
|
"gf_demo_02/internal/model/entity" |
||||
|
"gf_demo_02/internal/service" |
||||
|
"github.com/gogf/gf/v2/database/gdb" |
||||
|
"github.com/gogf/gf/v2/errors/gcode" |
||||
|
"github.com/gogf/gf/v2/errors/gerror" |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/util/gconv" |
||||
|
"golang.org/x/crypto/bcrypt" |
||||
|
"strings" |
||||
|
) |
||||
|
|
||||
|
type sUser struct { |
||||
|
} |
||||
|
|
||||
|
func init() { |
||||
|
service.RegisterUser(&sUser{}) |
||||
|
} |
||||
|
|
||||
|
func (u *sUser) GetUser(cond g.Map) (user *entity.User, err error) { |
||||
|
model := g.Model("user") |
||||
|
if cond["id"] != nil && gconv.Uint(cond["id"]) != 0 { |
||||
|
model = model.Where("id", cond["id"]) |
||||
|
} else if cond["name"] != nil && gconv.String(cond["name"]) != "" { |
||||
|
model = model.Where("name", cond["name"]) |
||||
|
} else { |
||||
|
return nil, gerror.NewCode(gcode.New(88, "缺少查询条件", nil)) |
||||
|
} |
||||
|
err = model.Scan(&user) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if user == nil { |
||||
|
return nil, gerror.NewCode(gcode.New(483, "用户不存在!", nil)) |
||||
|
} |
||||
|
return user, nil |
||||
|
} |
||||
|
|
||||
|
func (*sUser) GetUserList(ctx context.Context) (users []entity.User, err error) { |
||||
|
all, err := g.DB().Model("user").All() |
||||
|
if err != nil { |
||||
|
return nil, gerror.NewCode(gcode.New(599, "数据库error", nil)) |
||||
|
} |
||||
|
err = all.Structs(&users) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return users, nil |
||||
|
} |
||||
|
|
||||
|
func (*sUser) AddUser(ctx context.Context, req *user.EditUserReq) error { |
||||
|
u := entity.User{ |
||||
|
Id: req.Id, |
||||
|
Name: req.Name, |
||||
|
Pass: req.Pass, |
||||
|
Property: req.Property, |
||||
|
} |
||||
|
one, _ := g.Model("user").Where("name", req.Name).One() |
||||
|
if one != nil { |
||||
|
return gerror.NewCode(gcode.New(480, "用户名重复", nil)) |
||||
|
} |
||||
|
if len(req.Pass) < 6 { |
||||
|
return gerror.NewCode(gcode.New(481, "密码过短,至少6位", nil)) |
||||
|
} |
||||
|
password, err := bcrypt.GenerateFromPassword([]byte(u.Pass), 10) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
u.Pass = string(password) |
||||
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { |
||||
|
_, err = tx.Model("user").Insert(u) |
||||
|
return err |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
func (*sUser) UpdateUser(ctx context.Context, req *user.EditUserReq) error { |
||||
|
u := entity.User{ |
||||
|
Id: req.Id, |
||||
|
Name: req.Name, |
||||
|
Pass: req.Pass, |
||||
|
Property: req.Property, |
||||
|
} |
||||
|
one, _ := g.Model("user").Where("id", req.Id).One() |
||||
|
if one == nil { |
||||
|
return gerror.NewCode(gcode.New(483, "用户不存在!", nil)) |
||||
|
} |
||||
|
one, _ = g.Model("user").Where("name", req.Name).WhereNot("id", u.Id).One() |
||||
|
if one != nil { |
||||
|
return gerror.NewCode(gcode.New(480, "用户名重复", nil)) |
||||
|
} |
||||
|
if len(req.Pass) < 6 && req.Pass != "" { |
||||
|
return gerror.NewCode(gcode.New(481, "密码过短,至少6位", nil)) |
||||
|
} |
||||
|
if req.Pass != "" { |
||||
|
password, err := bcrypt.GenerateFromPassword([]byte(u.Pass), 10) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
u.Pass = string(password) |
||||
|
} |
||||
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { |
||||
|
model := tx.Model("user").OmitEmptyData() |
||||
|
result, err := model.Where("id", u.Id).Update(u) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
if affected, err := result.RowsAffected(); affected < 1 || err != nil { |
||||
|
return gerror.NewCode(gcode.New(500, "服务器错误", nil)) |
||||
|
} |
||||
|
return nil |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
func (*sUser) DeleteUser(ctx context.Context, req *user.DeleteUserReq) error { |
||||
|
one, _ := g.DB().Model("user").Where("id", req.Id).One() |
||||
|
if one == nil { |
||||
|
return gerror.NewCode(gcode.New(483, "用户不存在!", nil)) |
||||
|
} |
||||
|
tokenStr := g.RequestFromCtx(ctx).GetCtxVar("Authorization").String() |
||||
|
tokenStr = strings.TrimSpace(tokenStr) |
||||
|
tokenStr = strings.TrimPrefix(tokenStr, "Bearer ") |
||||
|
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { |
||||
|
_, err := tx.Model("user").Where("id", req.Id).Delete() |
||||
|
return err |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
func (*sUser) SearchUser(ctx context.Context, keyword string) ([]entity.User, error) { |
||||
|
all, err := g.Model("user").WhereLike("name", "%"+keyword+"%").All() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
users := make([]entity.User, 0) |
||||
|
err = all.Structs(&users) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
return users, nil |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
package model |
||||
|
|
||||
|
import "github.com/golang-jwt/jwt/v5" |
||||
|
|
||||
|
type UserClaim struct { |
||||
|
UserId uint |
||||
|
UserName string |
||||
|
jwt.RegisteredClaims |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// Course is the golang structure of table course for DAO operations like Where/Data.
|
||||
|
type Course struct { |
||||
|
g.Meta `orm:"table:course, do:true"` |
||||
|
Id interface{} //
|
||||
|
Name interface{} //
|
||||
|
Day interface{} //
|
||||
|
CreateAt *gtime.Time //
|
||||
|
UpdateAt *gtime.Time //
|
||||
|
DeleteAt *gtime.Time //
|
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// Stock is the golang structure of table stock for DAO operations like Where/Data.
|
||||
|
type Stock struct { |
||||
|
g.Meta `orm:"table:stock, do:true"` |
||||
|
Id interface{} //
|
||||
|
Name interface{} //
|
||||
|
Num interface{} //
|
||||
|
CreateAt *gtime.Time //
|
||||
|
UpdateAt *gtime.Time //
|
||||
|
DeleteAt *gtime.Time //
|
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// User is the golang structure of table user for DAO operations like Where/Data.
|
||||
|
type User struct { |
||||
|
g.Meta `orm:"table:user, do:true"` |
||||
|
Id interface{} //
|
||||
|
Name interface{} //
|
||||
|
Pass interface{} //
|
||||
|
Property interface{} //
|
||||
|
CreateAt *gtime.Time //
|
||||
|
DeleteAt *gtime.Time //
|
||||
|
UpdateAt *gtime.Time //
|
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package do |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
// UserCourse is the golang structure of table user_course for DAO operations like Where/Data.
|
||||
|
type UserCourse struct { |
||||
|
g.Meta `orm:"table:user_course, do:true"` |
||||
|
Uid interface{} //
|
||||
|
Cid interface{} //
|
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// Course is the golang structure for table course.
|
||||
|
type Course struct { |
||||
|
Id uint `json:"id" orm:"id" ` //
|
||||
|
Name string `json:"name" orm:"name" ` //
|
||||
|
Day string `json:"day" orm:"day" ` //
|
||||
|
CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` //
|
||||
|
UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` //
|
||||
|
DeleteAt *gtime.Time `json:"deleteAt" orm:"delete_at" ` //
|
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// Stock is the golang structure for table stock.
|
||||
|
type Stock struct { |
||||
|
Id uint `json:"id" orm:"id" ` //
|
||||
|
Name string `json:"name" orm:"name" ` //
|
||||
|
Num uint `json:"num" orm:"num" ` //
|
||||
|
CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` //
|
||||
|
UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` //
|
||||
|
DeleteAt *gtime.Time `json:"deleteAt" orm:"delete_at" ` //
|
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
import ( |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
// User is the golang structure for table user.
|
||||
|
type User struct { |
||||
|
Id uint `json:"id" orm:"id" ` //
|
||||
|
Name string `json:"name" orm:"name" ` //
|
||||
|
Pass string `json:"pass" orm:"pass" ` //
|
||||
|
Property uint `json:"property" orm:"property" ` //
|
||||
|
CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` //
|
||||
|
DeleteAt *gtime.Time `json:"deleteAt" orm:"delete_at" ` //
|
||||
|
UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` //
|
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
// =================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// =================================================================================
|
||||
|
|
||||
|
package entity |
||||
|
|
||||
|
// UserCourse is the golang structure for table user_course.
|
||||
|
type UserCourse struct { |
||||
|
Uid uint `json:"uid" orm:"uid" ` //
|
||||
|
Cid uint `json:"cid" orm:"cid" ` //
|
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package model |
||||
|
|
||||
|
import ( |
||||
|
"gf_demo_02/internal/model/entity" |
||||
|
"github.com/gogf/gf/v2/os/gtime" |
||||
|
) |
||||
|
|
||||
|
type CourseWithUsers struct { |
||||
|
Id uint `json:"id" orm:"id" ` //
|
||||
|
Name string `json:"name" orm:"name" ` //
|
||||
|
Day string `json:"day" orm:"day" ` //
|
||||
|
CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` //
|
||||
|
UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` //
|
||||
|
DeleteAt *gtime.Time `json:"deleteAt" orm:"delete_at" ` |
||||
|
Users []entity.User `json:"users"` |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
package packed |
||||
@ -0,0 +1,65 @@ |
|||||
|
package service |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"gf_demo_02/internal/consts" |
||||
|
"gf_demo_02/internal/model" |
||||
|
"strings" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
"github.com/gogf/gf/v2/net/ghttp" |
||||
|
"github.com/golang-jwt/jwt/v5" |
||||
|
) |
||||
|
|
||||
|
func JWTMiddleware(r *ghttp.Request) { |
||||
|
url := r.GetUrl() |
||||
|
if strings.HasSuffix(url, "/login") || strings.HasSuffix(url, "/loginPage") { |
||||
|
r.Middleware.Next() |
||||
|
return |
||||
|
} |
||||
|
tokenStr := r.Header.Get("Authorization") |
||||
|
tokenStr = strings.TrimSpace(tokenStr) |
||||
|
tokenStr = strings.TrimPrefix(tokenStr, "Bearer ") |
||||
|
if g.IsEmpty(tokenStr) { |
||||
|
r.Response.WriteStatus(401, "no token") |
||||
|
return |
||||
|
} |
||||
|
token, err := jwt.ParseWithClaims(tokenStr, &model.UserClaim{}, func(token *jwt.Token) (interface{}, error) { |
||||
|
_, ok := token.Method.(*jwt.SigningMethodHMAC) |
||||
|
if !ok { |
||||
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) |
||||
|
} |
||||
|
return []byte(consts.TOKEN_KEY), nil |
||||
|
}) |
||||
|
if err != nil { |
||||
|
r.Response.WriteStatus(401, "token invalid") |
||||
|
return |
||||
|
} |
||||
|
claim, ok := token.Claims.(*model.UserClaim) |
||||
|
if !ok || !token.Valid { |
||||
|
r.Response.WriteStatus(401, "token invalid") |
||||
|
return |
||||
|
} |
||||
|
id := claim.UserId |
||||
|
name := claim.UserName |
||||
|
cond := g.Map{ |
||||
|
"id": id, |
||||
|
"name": name, |
||||
|
} |
||||
|
user, err := User().GetUser(cond) |
||||
|
if err != nil || user == nil { |
||||
|
r.Response.WriteStatus(401, "token invalid") |
||||
|
return |
||||
|
} |
||||
|
if user.Id != id || user.Name != name { |
||||
|
r.Response.WriteStatus(401, "token invalid") |
||||
|
return |
||||
|
} |
||||
|
r.SetCtxVar("user", user) |
||||
|
r.Middleware.Next() |
||||
|
} |
||||
|
|
||||
|
func CorsMiddleware(r *ghttp.Request) { |
||||
|
r.Response.CORSDefault() |
||||
|
r.Middleware.Next() |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
package service |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
|
||||
|
"golang.org/x/crypto/bcrypt" |
||||
|
) |
||||
|
|
||||
|
// bcrypt加密
|
||||
|
func encode() { |
||||
|
password, err := bcrypt.GenerateFromPassword([]byte("123"), 10) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
fmt.Println(string(password)) |
||||
|
err = bcrypt.CompareHashAndPassword(password, []byte("123")) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
fmt.Println("correct") |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
package service |
||||
|
|
||||
|
import "testing" |
||||
|
|
||||
|
func TestEncode(T *testing.T) { |
||||
|
encode() |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
// ================================================================================
|
||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
|
// You can delete these comments if you wish manually maintain this interface file.
|
||||
|
// ================================================================================
|
||||
|
|
||||
|
package service |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"gf_demo_02/api/user/v1" |
||||
|
"gf_demo_02/internal/model/entity" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/frame/g" |
||||
|
) |
||||
|
|
||||
|
type ( |
||||
|
IUser interface { |
||||
|
GetUser(cond g.Map) (user *entity.User, err error) |
||||
|
GetUserList(ctx context.Context) (users []entity.User, err error) |
||||
|
AddUser(ctx context.Context, req *user.EditUserReq) error |
||||
|
UpdateUser(ctx context.Context, req *user.EditUserReq) error |
||||
|
DeleteUser(ctx context.Context, req *user.DeleteUserReq) error |
||||
|
SearchUser(ctx context.Context, keyword string) ([]entity.User, error) |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
var ( |
||||
|
localUser IUser |
||||
|
) |
||||
|
|
||||
|
func User() IUser { |
||||
|
if localUser == nil { |
||||
|
panic("implement not found for interface IUser, forgot register?") |
||||
|
} |
||||
|
return localUser |
||||
|
} |
||||
|
|
||||
|
func RegisterUser(i IUser) { |
||||
|
localUser = i |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
_ "gf_demo_02/internal/packed" |
||||
|
|
||||
|
_ "gf_demo_02/internal/logic" |
||||
|
|
||||
|
"github.com/gogf/gf/v2/os/gctx" |
||||
|
|
||||
|
"gf_demo_02/internal/cmd" |
||||
|
|
||||
|
_ "github.com/gogf/gf/contrib/drivers/mysql/v2" |
||||
|
) |
||||
|
|
||||
|
func main() { |
||||
|
cmd.Main.Run(gctx.GetInitCtx()) |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
apiVersion: apps/v1 |
||||
|
kind: Deployment |
||||
|
metadata: |
||||
|
name: template-single |
||||
|
labels: |
||||
|
app: template-single |
||||
|
spec: |
||||
|
replicas: 1 |
||||
|
selector: |
||||
|
matchLabels: |
||||
|
app: template-single |
||||
|
template: |
||||
|
metadata: |
||||
|
labels: |
||||
|
app: template-single |
||||
|
spec: |
||||
|
containers: |
||||
|
- name : main |
||||
|
image: template-single |
||||
|
imagePullPolicy: Always |
||||
|
|
||||
@ -0,0 +1,8 @@ |
|||||
|
apiVersion: kustomize.config.k8s.io/v1beta1 |
||||
|
kind: Kustomization |
||||
|
resources: |
||||
|
- deployment.yaml |
||||
|
- service.yaml |
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,12 @@ |
|||||
|
apiVersion: v1 |
||||
|
kind: Service |
||||
|
metadata: |
||||
|
name: template-single |
||||
|
spec: |
||||
|
ports: |
||||
|
- port: 80 |
||||
|
protocol: TCP |
||||
|
targetPort: 8000 |
||||
|
selector: |
||||
|
app: template-single |
||||
|
|
||||
@ -0,0 +1,14 @@ |
|||||
|
apiVersion: v1 |
||||
|
kind: ConfigMap |
||||
|
metadata: |
||||
|
name: template-single-configmap |
||||
|
data: |
||||
|
config.yaml: | |
||||
|
server: |
||||
|
address: ":8000" |
||||
|
openapiPath: "/api.json" |
||||
|
swaggerPath: "/swagger" |
||||
|
|
||||
|
logger: |
||||
|
level : "all" |
||||
|
stdout: true |
||||
@ -0,0 +1,10 @@ |
|||||
|
apiVersion: apps/v1 |
||||
|
kind: Deployment |
||||
|
metadata: |
||||
|
name: template-single |
||||
|
spec: |
||||
|
template: |
||||
|
spec: |
||||
|
containers: |
||||
|
- name : main |
||||
|
image: template-single:develop |
||||
@ -0,0 +1,14 @@ |
|||||
|
apiVersion: kustomize.config.k8s.io/v1beta1 |
||||
|
kind: Kustomization |
||||
|
|
||||
|
resources: |
||||
|
- ../../base |
||||
|
- configmap.yaml |
||||
|
|
||||
|
patchesStrategicMerge: |
||||
|
- deployment.yaml |
||||
|
|
||||
|
namespace: default |
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,16 @@ |
|||||
|
FROM loads/alpine:3.8 |
||||
|
|
||||
|
############################################################################### |
||||
|
# INSTALLATION |
||||
|
############################################################################### |
||||
|
|
||||
|
ENV WORKDIR /app |
||||
|
ADD resource $WORKDIR/ |
||||
|
ADD ./temp/linux_amd64/main $WORKDIR/main |
||||
|
RUN chmod +x $WORKDIR/main |
||||
|
|
||||
|
############################################################################### |
||||
|
# START |
||||
|
############################################################################### |
||||
|
WORKDIR $WORKDIR |
||||
|
CMD ./main |
||||
@ -0,0 +1,8 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
# This shell is executed before docker build. |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||