(7月1日)
上午 :
1、类,成员变量,构造函数,方法。
2、代码分析项目:版本表的analysis_spend的值的计算有问题,应该用分析的开始时间减当前的(子)任务结束时间,这个分析的开始时间在记录任务开始时间日志的时候就要设置到数据库中 ,不然任务结束才设置,逻辑就错了,analysis_spend的值就有错误。
3、新增漏洞接口新增的东西找不到,只在最新的才能添加?:添加新漏洞的时候,只被提供一个版本id,没有扫描信息相关的id的内容,但一个版本id对应多个扫描信息,新添加的漏洞只能选此版本中的一个扫描信息来添加漏洞,那就是新设置的 “手动添加漏洞项”,
下午:
1、找到为什么返回的子任务详情内容为null的原因,
2、找到为什么日志文件中的内容有时不是一个单独的json,会重复两个或多个json,写入的时候,没有提前被清空?有时甚至会直接把服务给断了?(代码不变情况下,随机发生)
3、函数中有defer 执行的函数 与 go协程执行的长时间内部函数,这个函数的执行顺序是什么:
“go关键字创建一个新的goroutine时,该goroutine会在后台并发执行,而不会阻塞原函数的执行。”,
“意味着,即使go创建的新协程还没有执行完,defer指定的函数也会在原函数执行完毕时开始执行”,
“因此,如果在defer语句中依赖于go创建的新协程的执行结果,可能会导致不符合预期的结果。”
以上是下午1问题的原因。
解决:找到子任务日志写入完成的那个点,时间点代码位置点,在这个地方读日志。在哪里?
把读子任务日志的代码放在了与s.StartScanTask()方法并列的defer方法中,子任务内容可以正常读并输出,不为空了。
4、“一个函数中,有个defer 调用函数A,还有一个普通的函数调用B,但这个普通的函数调用B里有go协程的使用来调用C”,函数C的执行是在一个新的go协程中,并行于函数B和函数A的执行。
5、漏洞添加,往版本的手动类添加的时候,需要把At_latest 设置为true,不然进行结果查询的时候查不到此版本手动添加的漏洞,
6、APIfox白屏,打不开关不掉: Ctrl+Shift+Esc
或Ctrl+Alt+Delete
后打开任务管理器,关。
7、
(7月2日)
上午:
1、不是调用开始扫描的时候,后端服务会被断掉,是开始扫描后,再调用读日志的时候后端被断掉的。推断可能原因:此次的开始扫描的调用没有正确生成文件,
解决:是,就是上面原因,一样的请求多等一会儿文件夹中有文件出现,就可以正确读不会断服务。
2、后端服务被断掉情况的常见原因:硬件故障、操作系统崩溃、内存溢出、资源耗尽等;
3、昨天下午问题2:“一个.log文件中按理只有一个json才可以被正确解析,但有时会在日志中写入两个,”
解决:
4、子任务详情为什么一直只返回一句话:“某语言不支持Language go is not supported”,之后这里应该还有问题需要解决,
下午:
1、os.OpenFile()时,
os.O_TRUNC
标志会在打开文件时将文件截断为0字节,即清空文件内容。
os.O_APPEND
标志会将写入的内容追加到文件末尾。
os.O_CREATE
如文件不存在,则创建文件。如果文件已存在,则不操作。
os.O_WRONLY
:以只写模式打开文件。
os.ModePerm
是Go中os
包中定义的文件权限常量,表示最高,值是0777
。
在打开文件的时候,加上os.O_TRUNC标志,可暂时解决返回两个json问题。但实际原因还未定位到,为什么一次扫描会有两次结果信息在日志中写入,
2、为什么结果会不稳定,有时出现以下报错:
“message”: “invalid character ‘{’ after top-level value”,
原因可能是如下图:每次写入新数据的时候,需要把旧数据先清空,再写入最新的json结构数据,这部分是在go协程中实现的,但好像也不太对,下面都有Write,
但更好的解决办法好像没有,
3、string()
函数只能用于将整数类型的Unicode码点转换为对应的字符串。
go中’‘表示字符,“”表示字符串,
strconv包用来转换格式,但没直接字符转串的,
(7月3日)
上午:
1、Git提交规范:
feat: 新增了个功能;
fix: 发现并修复了一个bug ;
chore:进行一些与代码逻辑无关的工作,比如更新文档、调整代码格式、优化构建过程等 ;
2、对于长度为0,容量为10的切片,可以通过索引来逐个赋值,但是需要使用append函数来添加元素,而不是直接通过索引赋值。
subTask := make([]map[string]interface{}, 0, 10)
//subTask[0] = make(map[string]interface{}) //会报错
subTask = append(subTask, make(map[string]interface{})) //不会报错
再subTask[0][“key”] = “value”
3、
下午:
1、数组格式优化了下
2、子任务耗时想保留两位返回给前端,前端做了,若后端做得转成字符串处理,如下,
subTaskEndTime := scanInfo.StartTime.Sub(scanInfo.EndTime).Abs().Seconds()
subresult := map[string]interface{}{
“subTaskEndTime”: fmt.Sprintf(“%.2f”, subTaskEndTime),
}
3、获取子任务的状态和耗时需要在StartScanTask->OnEndTaskProcess方法内部获得,通数据库查询得到,
4、为什么任务的开始时间与结束时间之差和子任务的总时间不相等,前小于后:各个子任务是并行的,有的时间是重叠的,
5、taskNumber,taskEndTime,version.Update()部分必须放在defer中,不然响应的结果中的taskNumber值总为0,任务结束时间taskEndTime也是不对的,库中版本表中对任务数的计数也是不对的成0了,
原因:上层函数执行完,内部的各个子任务go还没执行完,
6、不需要创建新的日志文件?
那意思是,在读的逻辑中,不用实现那么简单只读一个文件中的json数据,可以稍复杂点,在这里:时间查数据库,子任务详情查日志文件,
这样扫描逻辑是基本不用改的,总之是相对不用那么复杂,
执行过程与问题:不同的子任务名可能要进行遍历才能在数据库中查询,但是怎么在读日志的接口中获得这个版本的最新的不同子任务的名字呐?在扫描的时候存一下吗,存哪里?
(7月4日)
上午:
1、使用logfile, err := os.OpenFile(LogPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
做不到不同次的write写入是先清空上次的写入再进行这次的write,实际结果是接在文件的后面来写的,一直都没有被清空,
2、如果另外在读接口中,才把所有数据整合起来,四个子任务名从哪里获得,不存在怎么保证输出的顺序 -> 可以查,按照“version_id”与“is_latest”字段查,但是这里有个问题 ,“is_latest”字段是怎么变化的,在某个版本id创建新的子任务的时候,原本为1的会自动变成0吗,创建时陆续变还是一起变?->是一起先统一都设置为0了然后才一个个子任务给创建新的扫描信息。那查的时候怎么分清先后呐,需要分清先后吗?好像不需要,
任务开始时间,扫描中需要先清空还是先设置为0,那读的时候要等待吗,还是先直接返回空,再查有数据就返回数据,(新扫描开始时,分析时间可被设置为空,还未设)
任务数 怎么保证对 (新扫描开始时,被设置为0,已设)
任务结束时间怎么保证输出的是最新的,因为这部分要查版本表,但版本表中已经有上次的开始分析时间与花费时间的数值这情况怎么区分,新扫描开始时,分析费时analysis_spend需被设置为0,分析时间可被设置为空,都还未设)
3、清空文件的方法的替换:
原来: _ = ioutil.WriteFile(LogPath, []byte{}, 0644) //放在打开文件后
换为: err := os.Truncate(LogPath, 0) //放在打开文件前
下午:
1、原本子任务的状态与耗时的设置是在OnEndTaskProcess方法中,但子任务内容的设置不能在这个方法中进行会为null,只好放在了外层函数的defer中,这样就分开设置了,不太合理
优化:把外层函数defer中的一堆内容放到一个新的方法中,子任务的状态与耗时的设置也提出来一起在这个方法中设置,
2、map的赋值不能如下:
var subresult map[string]interface{} 然后就subresult[“subTaskContent”] = content了,会报错
应该如下:
subresult := map[string]interface{}{ “subTaskSpendTime”: scanInfo.StartTime.Sub(scanInfo.EndTime).Abs().Seconds()}
原因:q前者声明时,该变量是一个空map,还没有被分配内存空间。
有两种做法:
一是使用make
函数来创建一个非空的map,然后再进行赋值,subresult := make(map[string]interface{})
二是使用字面量的方式直接初始化一个非空的map,就像原因上面那个方法。
3、Ctrl结构体里的toolsProcess是个什么?怎么起作用的?接着Ctrl里的别的都起什么作用呐?
(7月5日)
上午:
1、思路整理:
扫描部分现在大概过程是在扫描的时候就将任务开始时间,子任务内容与耗时与状态,任务数,任务结束时间,都一起从数据库中抽取出来放到一个专门的本版本的日志文件中(如下图文件对应),其中子任务也有专门的日志文件但里面只有子任务详情没有其他内容,这个又新建的日志文件是用来把所有的扫描详情用到的内容集合起来,有新的内容就清空并重写更新这个文件,以便于读接口直接读这个文件,获得最新内容,
在读日志的接口中,直接读这个新建的文件,获得最新的json内容,
上次展示的那个错误,后来把defer里的逻辑给抽取出来放到了几个新的方法中,这个报错就没了,
(这样的几个方法),目前前端所需内容基本都可以通过后端服务给显示成功,
要改进的逻辑:
在扫描接口中不新建一个集合所有所需内容的文件,只在扫描前该清空相应值就清空,扫描中有新数据该存就存,别的不操作,
在读日志的接口中再把这些详情内容集合起来,由于现在不能只读日志就一下获得所有所需内容,所以过程是:其中任务开始时间,子任务耗时与状态,任务数,任务结束时间都是当即从数据库中分别查找到的,子任务内容是当即从对应的子任务日志中查到的,在响应中用结构体存各个内容返回,
2、上次那个运行服务接口使服务直接的原因是,被强制退出了,大概是因为某个函数调用没有返回err并判空,
3、正则表达式:{}
用于指定匹配的次数,
. 匹配任意单个字符。匹配前面的字符中括号:。
?:匹配前面的字符零次或一次。
[]:匹配方括号中的任意一个字符。
():分组,用于限定匹配的范围。
\:转义字符,用于匹配特殊字符本身。
下午:
1、这里sync.Map的dirty的键值的值用了不同原本entry的结构,type entry struct{ p atomic.Pointer[any] }和type entry struct{ p unsafe.Pointer } ,第一个结构体使用了原子指针类型,而第二个结构体使用了普通的指针类型,需要开发者自行保证并发安全性。
2、map底层,为解决多个元素映射到同一个哈希桶时的冲突,哈希表采用了链地址法,插入时桶中有元素则遍历链表,将新元素插入到链表的末尾。
(7月8日)
上午:
1、把上周五的改进想法跑通实现。
2、 result[“taskEndTime”] = version.AnalysisTime.Add(time.Duration(version.AnalysisSpend) * time.Second).Format(“2006-01-02 15:04:05”)
这句,不能直接用 result[“taskEndTime”] = version.AnalysisTime.Add(time.Duration(version.AnalysisSpend)).Format(“2006-01-02 15:04:05”)
这样时间间隔会自动识别为纳秒,结果不对
下午:
1、 time.Time
的零值是 time.Time{}
。
2、疑问:OnNewTaskProcess()中为什么不设置SetIsLatest呐?
3、撤销了一个提交后drop commit,原来写在里面的代码没被commit的部分也会被消失,可以在此文件中按上面的undo键,会给个提示是否重加载桌面文件内容,是,便可恢复。
4、Goroutine是有栈协程,go中没有直接支持无栈协程。
5、代码比对部分:(从哪里入手理出正确逻辑,怎么写)
新需求;
(7月9日)
上午
1、代码对比部分:wsl,diff或go-diff包,
2、在WSL环境中部署Code-Server:可以通过访问http://127.0.0.1:8080来访问Code-Server,可在浏览器中打开Code-Server的Web界面,从而访问和使用WSL环境中的开发工具和编辑器。这样就可以通过浏览器进行远程开发,而无需在本地安装和配置开发环境。
<a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a>
是HTML中的一句代码,用于创建一个超链接。
通过部署Code-Server的好处:可以远程开发,跨平台开发,资源隔离,云端开发,
3、指定文件与行数:
代码中的folder
参数指定了要打开的文件所在的文件夹路径,payload
参数是一个数组,包含了两个元素。第一个元素["gotoLineMode", "true"]
表示开启跳转到指定行数的模式,第二个元素["openFile", "vscode-remote:///mnt/c/Users/admin/Desktop/1.txt:21"]
表示要打开的文件路径和行数。
将以上参数拼接到Code-Server的URL中,可以在打开Code-Server时指定要打开的文件、行数和列数。这样在浏览器中打开该URL后,Code-Server会自动打开指定的文件,并将光标定位到指定的行数和列数。
4、指定文件夹比对:
两个参数compareFolders.folderLeft
和compareFolders.folderRight
,用于指定要比对的两个文件夹路径。
5、- 相比于Select,Poll没有最大文件描述符数量的限制,可以动态管理文件描述符集合的大小。- Epoll使用一个事件表来表示文件描述符集合,通过事件驱动的方式,只返回就绪的文件描述符,边缘触发。
下午:
1、版本表中给出的上传文件(乱码)怎么打开,怎么用,
2、Go语言中有代码对比库,diff或go-diff,是要用这些来进行对比吗,对比出个什么,不同的挑出来吗。是用插件来完成对比的,插件怎么用到程序中呐?
3、理清这个代码对比的接口,
开始:接收两个版本id,
中间:根据id查库,得到两个代码文件(这个代码文件是版本表upload_time字段中的内容?这里的文件名好像没有后缀)通过Code-Server的URL来打开文件(这里还可以指定行数,是只对某一行对比吗,不是全文嘛?还有对比的结果是什么需要管吗);通过Compare-folders插件来完成对比;
结束:给出一个插件生成的对比完的项目地址?
解决:不是读文件是读文件夹,指定行是另外一个接口功能在“结果查看”那里,
4、小问题点:怎么读到这两个文件夹,用url吗但这不是另外一个接口用到的;怎么在接口中使用Code-Server,用cmd命令行吗;我这边处理codesever中的功能实现,前端调用我这边主机(127.0.0.1:8080)接口来使用类似浏览器功能来获得服务器这边的页面内容。
5、exec.Command("wsl", "code-server", "--install-extension", "moshfeu.compare-folders", folder, payload)
创建了一个Cmd
对象,表示要在Windows Subsystem for Linux (WSL)中执行code-server
命令,并传递了一些参数。然后,cmd.Run()
方法执行该命令,
(7月10日)
上午:
1、要是想实现一个Go的接口,首先有两个文件夹地址放有两个项目,这个接口功能上能实现两个项目的内部代码对比,最后将对比后的代码连同vscode界面服务一起返回给前端,其中会使用到上面几段对话中的 wsl技术,code-server,Compare-folders 插件等技术。请问这个接口应该怎么写
2、为什么前端要连接127.0.0.1:8080端口才能获得vscode页面服务,我是怎么把这个功能放到这个端口上的,前端对这个端口的访问和对正常api接口的访问是一样的吗
解决:code-server就是干这个的,
3、代码对比功能 是通过配置文件来搞的,把两个项目的地址放入嵌入到配置文件中,然后开始对比分析,
怎么确定对比完了,会有个信号吗,解决:对比就是把地址配置上就行,
怎么放入到配置文件中呐,用命令行吗,解决:SetCompareFolders方法里处理,
4、
wsl: 允许在Windows操作系统上运行Linux子系统,有两个版本,
code-server: 允许用户通过Web浏览器访问和使用VS Code的功能。提供了一个基于Web的IDE(集成开发环境),使用户可以在任何设备上通过浏览器进行代码编辑、调试和开发。
Compare-folders: 一个VS Code的插件,用来比较和同步两个文件夹之间的差异。
5、看看ubuntu2004中的方法怎么用在compare接口中,
6、写还算容易,但理解业务有点花时间,
下午:
1、数据库表中的地址中是‘'不是方法中的’\‘,需要改吗?
不用,字符串中的反斜杠(\)需要使用两个反斜杠(\)来表示,转义字符。
2、项目地址放入到配置文件后,怎么运行这个配置文件以最终实现对比呐?
3、管理员启动powershell,
4、直接在powershell中wsl,可以进入ubuntu。
5、/mnt/c/
可以理解为Windows系统中的C盘根目录在WSL中的路径表示方式,
6、明天把要对比的文件放在ubuntu目录下看看,直接c://应该不行,
(7月11日)
上午:
1、要读的文件的地址要换成ubuntu中能读windows文件的路径形式,json配置地址则可以不用。
2、指定行功能,这块有什么要求吗?昨天说原型图中地址名加有行数,根据这个行来指定吗,这一块原本要求的逻辑是什么,
接口逻辑:
开始:需要文件名,行数。从前端获得扫描结果ID,由id查file_path(都是.jsp文件),code_snippet? , line_number?,
中间:在默认值置为“”, 用GetSpecialLineUrl()方法处理,
最后:把带有folder,file,line的url放响应中返回给前端,
3、要指定行和列,列是什么?这里应该不用列,
下午:
对齐,
(7月12日)
上午:
1、修改代码比对接口的路径处理。
2、对比时如果两个文件相同相等,那么在浏览器访问的code-server中不会出现对比结果的展示,只有两者有所不同,调用接口后再刷新后才会显示。
下午:
1、昨天遇到前端无法访问我这边服务的端口的问题,
昨天的解决:在终端使用了:sudo code-server --auth none --bind-addr 0.0.0.0:8080
原理:其是将code-server绑定到本机的所有IP地址的8080端口,使得其他设备可以通过局域网中的IP地址来访问code-server。而 sudo code-server --auth none --port 8080 则只能在本机通过localhost来访问code-server。本地回环接口(127.0.0.1),只能通过本地访问。
2、defer关键字的实现原理,关于panic:
panic时,程序会立即停止当前函数的执行,创建panic对象,其中包含了panic的值以及当前的调用栈信息。
程序开始沿着调用栈向上寻找defer语句。在每个defer语句中,如果存在recover函数调用,那么程序会继续执行,并将panic对象传递给recover函数。 recover函数会判断传入的参数是否为panic对象。如果是,它会停止panic的传播,并返回panic的值。如果不是,它会返回nil。
当程序执行完所有的defer语句后,如果没有遇到recover函数调用,或者recover函数返回nil,那么程序会终止并打印panic的值以及调用栈信息。
defer关键字的实现原理是通过在发生panic时,沿着调用栈寻找defer语句,并将panic对象传递给recover函数来实现的。
3、string底层是byte类型的数组,(和slice类似,底层是数组),
4、可以使用Streamlit开发前端网页,并使用Go语言开发后端服务,但需要将它们分别部署在不同的环境中,并通过网络通信进行交互。
(7月15日)
上午:
1、go 的高并发体现在,协程,通道,select,sync Mutex和RWMutex:互斥锁读写锁,sync WaitGroup,context,
通道在close时会通知所有监听它的协程,context就有利用这一特性。
2、看原型图。项目最后还要三方评审:产品,设计,研发团队评审。
下午:
3、ent数据库操作框架的使用:
定义模型: 首先,你需要定义你的数据模型。在ent中,你可以使用类似于结构体的方式来定义模型,包括字段、关联关系等。Fields(),Edges(),
生成代码: 在定义好模型后,你需要使用ent命令行工具来生成相应的代码。命令:ent generate ./schema
创建客户端: 在使用ent框架之前,你需要创建一个ent客户端来连接数据库。你可以使用ent.Open函数来创建一个客户端实例,指定数据库的连接信息。client, err := ent.Open(“sqlite3”, “file:entdemo.db?cache=shared&_fk=1”)
数据操作: 通过ent客户端,你可以进行各种数据库操作,如创建、查询、更新和删除数据等。
4、imroc/req 和gin:如果你只是想要发送HTTP请求并获取电影信息,你可以只使用imroc/req
库。如果你想要构建一个完整的Web应用程序,你可以使用Gin框架。
前者发送HTTP请求,后者主要处理HTTP请求并构建Web应用程序,
5、context:
父: (根级上下文通常不需要被取消,因为它们没有明确的超时或取消条件。)
context.Background():这是一个空的上下文对象,通常用作父级上下文。它没有任何值、超时或取消功能。
context.TODO():这也是一个空的上下文对象,类似于context.Background(),但是在不确定使用哪种上下文时使用。常用作临时占位。
子:
context.WithCancel(parent):这个函数返回一个带有取消功能的子级上下文。当调用返回的cancel函数时,该上下文及其所有子级上下文都会被取消
context.WithDeadline(parent, deadline):这个函数返回一个带有截止时间功能的子级上下文。当截止时间到达时,该上下文及其所有子级上下文都会被取消。
context.WithTimeout(parent, timeout):这个函数返回一个带有超时功能的子级上下文。当超时时间到达时,该上下文及其所有子级上下文都会被取消。