SpringBoot 整合knife4j
文章目录
- SpringBoot 整合knife4j
- 引入knife4j
- 注解
- 案例
- knife4j增强功能
- 接口添加作者
- 资源屏蔽
- 访问页面加权控制
- 接口排序
- 分组排序
- 请求参数缓存
- 过滤请求参数
- 禁用调试
- 禁用搜索框
SpringBoot 整合knife4j
Knife4j是一款基于Swagger 2的在线API文档框架
在Spring Boot中,使用此框架时,需要:- 添加依赖
- 在配置文件(`application.properties`)中开启增强模式
- 编写配置类(代码相对固定,建议CV)
引入knife4j
添加依赖
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency>
创建 Swagger 配置依赖
package com.yolo.knife4j.config;import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.*;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;@Slf4j
@Configuration
@EnableSwagger2WebMvc
// 对JSR303提供支持
@Import(BeanValidatorPluginsConfiguration.class)
public class Knife4jConfig {@Value("${spring.application.name}")private String applicationName;@Beanpublic Docket defaultApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName(applicationName).select()// 添加@Api注解才显示.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))// 这里指定Controller扫描包路径
// .apis(RequestHandlerSelectors.basePackage("com.yolo")).paths(PathSelectors.any()).build();}/*** swagger-api接口描述信息*/private ApiInfo apiInfo() {return new ApiInfoBuilder().title("API文档").description("API文档").contact(new Contact("yolo","https://gitee.com/huanglei1111","2936412130@qq.com")).version("1.0.0").build();}
}
application.yml配置文件
# https://doc.xiaominfo.com/knife4j
knife4j:# 开启增强配置enable: true# 是否开启生产环境屏蔽 true:关闭swagger,false:开启swaggerproduction: falsebasic:# 是否开启认证enable: false# Basic认证用户名username: admin# Basic认证密码password: 123456
spring:application:name: test-knife4j
注解
@Api(tags = {“用户操作”})
加在controller类上
tags表示该类的标签,在页面会独立显示一个菜单@ApiOperation(value = “保存用户”, notes = “保存时,ID由数据库生成,无需填写,有则忽略”, tags = “保存”)
加在相应的请求处理方法上
value表示该方法的说明
notes相当于对该方法的详细说明,也就是更加完整的描述
tags 表示标签,,在页面会独立显示一个菜单@ApiImplicitParam(name = “id”, value = “用户ID”, defaultValue = “1”)
方法只有一个基本类型参数时加在方法上。方法有多个参数时加在@ApiImplicitParams内
name 参数中属性的名字
value 对这个属性的描述
defaultValue 默认值,这个还是有必要填写的,在页面进行请求时,会自动填充@ApiImplicitParams(value = {})
用在请求方法上
这个注解必须和@ApiImplicitParam配合使用
当请求方法中的请求参数很多的时候,例如saveUser(String username, Integer age, Date birthday, String phone)@ApiParam(value = “当前页”, defaultValue = “1”)
加在请求方法的普通参数上
value的值是对该参数的说明
与@ApiImplicitParam使用的效果等同,根据个人喜好进行使用@ApiModel(value = “用户信息”)
加在请求方法的对象类上
value 对该对象参数的描述
例如有一个请求方法save(UserDTO userDTO), 则需要加在UserDTO这个类上面(可以参照下面的示例)@ApiModelProperty(value = “用户ID”, example = “1”)
加在请求方法的参数对象的属性上
value 对该属性的描述
example 属性的示例值,在页面会自动填充该值@ApiIgnore:注解类、参数、方法,注解后将不在Swagger UI中显示
案例
package com.yolo.knife4j.controller;import cn.hutool.core.collection.ListUtil;
import com.yolo.knife4j.base.ResultVo;
import com.yolo.knife4j.dto.UserAddRequest;
import com.yolo.knife4j.vo.StudentVO;
import com.yolo.knife4j.vo.UserVO;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.Date;@ApiResponses(value = {@ApiResponse(code = 200, message = "接口返回成功状态"),@ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
})
@Api(tags = "用户")
@RestController
@RequestMapping("/user")
public class UserController {@ApiOperation(value = "保存用户", notes = "简单传参")@PostMapping("/add")public ResultVo<Object> add(@RequestBody @Valid UserAddRequest userAddRequest) {return ResultVo.builder().build().setCode(200).setSuccess(true).setTime(new Date()).setMsg("保存用户成功").setData(userAddRequest);}@ApiOperation(value = "保存用户2", notes = "复杂传参")@PostMapping("/add2")public ResultVo<Object> add2(@RequestBody @Valid UserAddRequest userAddRequest) {return ResultVo.builder().build().setCode(200).setSuccess(true).setTime(new Date()).setMsg("保存用户成功").setData(userAddRequest);}@GetMapping("/list")@ApiOperation(value = "查找用户列表", notes = "根据id查找单个用户")public ResultVo<Object> list(@RequestParam @ApiParam(value = "当前页", defaultValue = "1") Integer pageNum,@RequestParam @ApiParam(value = "页大小", defaultValue = "10") Integer pageSize) {UserVO vo = new UserVO();StudentVO studentVO = StudentVO.builder().build().setAddress("wuhan").setCode(2);vo.setStudentVOS(ListUtil.of(studentVO));return ResultVo.builder().build().setCode(200).setSuccess(true).setTime(new Date()).setMsg("查找用户列表").setData(vo);}@DeleteMapping("/{id}")@ApiOperation(value = "删除用户", notes = "删除后无法恢复")@ApiImplicitParam(name = "id", value = "用户ID", defaultValue = "1")public ResultVo<Object> delete(@PathVariable(name = "id") Long id) {return ResultVo.builder().build().setCode(200).setSuccess(true).setTime(new Date()).setMsg("删除用户");}
}
响应参数
package com.yolo.knife4j.base;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;import java.io.Serializable;
import java.util.Date;@Data
@Builder
@Accessors(chain = true)
@ApiModel("响应参数")
@AllArgsConstructor
@NoArgsConstructor
public class ResultVo<T> implements Serializable {private static final long serialVersionUID = -8054007511410819665L;@ApiModelProperty(value = "响应状态码", example = "1", dataType = "Integer")private int code;// 是否成功标识.true表示成功,false表示失败@ApiModelProperty("success标识,true表示成功,false表示失败")private boolean success;// 操作成功时需要响应给客户端的响应数据@ApiModelProperty("响应信息")private String msg;@ApiModelProperty("响应数据")private T data;@ApiModelProperty("当前时间")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date time;
}
tips: http://127.0.0.1:8080/doc.html
这里端口,就是你运行项目的端口
knife4j增强功能
springboot 中 knife4j的完整参数如下:
knife4j:enable: truedocuments:-group: 2.X版本name: 接口签名locations: classpath:sign/*setting:language: zh-CNenableSwaggerModels: trueenableDocumentManage: trueswaggerModelName: 实体类列表enableVersion: falseenableReloadCacheParameter: falseenableAfterScript: trueenableFilterMultipartApiMethodType: POSTenableFilterMultipartApis: falseenableRequestCache: trueenableHost: falseenableHostText: 192.168.0.193:8000enableHomeCustom: truehomeCustomLocation: classpath:markdown/home.mdenableSearch: falseenableFooter: falseenableFooterCustom: truefooterCustomContent: Apache License 2.0 | Copyright 2019-[浙江八一菜刀股份有限公司](https://gitee.com/xiaoym/knife4j)enableDynamicParameter: falseenableDebug: trueenableOpenApi: falseenableGroup: truecors: falseproduction: falsebasic:enable: falseusername: testpassword: 12313
接口添加作者
添加作者有俩种方式
- 在方法上使用注解
@ApiOperationSupport(author = "yolo-test")
- 在controller类上使用注解
@ApiSupport(author = "yolo-controller")
如果在方法上使用了注解,并且也在类上使用了注解,那么最后的展示结果以方法上的注解为准
资源屏蔽
当我们在生成环境的时候不想显示接口文档,由于 Knife4j 基于 Servlet 体系提供了过滤 Filter 功能,所以就不需要我们再去造轮子了,直接使用即可
knife4j:# 开启增强配置enable: true# 是否开启生产环境屏蔽 true:关闭swagger,false:开启swaggerproduction: true
然后重启项目
访问页面加权控制
针对Swagger的资源接口,Knife4j提供了简单的Basic认证功能
简单点说,指定一个用户名和密码,访问 Swagger 文档需要验证登录名和密码,验证通过之后才能正常访问
如果用户开启了 basic (knife4j.basic.enable = true)认证功能,但是没有指定 username 和password,那么 knife4j 提供了一组默认的用户名密码
admin/123321
knife4j:# 开启增强配置enable: true# 是否开启生产环境屏蔽 true:关闭swagger,false:开启swaggerproduction: falsebasic:# 是否开启认证enable: true# Basic认证用户名username: admin# Basic认证密码password: 123456
如果开启生产环境屏蔽了,开启basic认证是不生效的
接口排序
@ApiOperationSupport注解中增加了 order 字段,用于接口排序。在使用此注解之前需要开启增强功能
分组排序
分组,顾名思义,就是多个 controller 之间的排序,开发者可以通过注解实现每个controller 之间的排序,实现这个功能的注解一共有三个,具体如下
@ApiSupport
@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "yolo-controller",order = 999)
@Api(tags = "测试swagger")
public class Knife4jTestController
@ApiSort
@RestController
@RequestMapping(value = "/test")
@ApiSort(value = 999)
@Api(tags = "测试swagger")
public class Knife4jTestController
@Api
@RestController
@RequestMapping(value = "/test")
@Api(tags = "测试swagger",position = 999)
public class Knife4jTestController
Tips:
这三个注解是存在优先级的,也就是说,当同时使用时,只会有一个注解生效,所以在使用的时候需要特别注意。优先级规则如下
@ApiSupport > @ApiSort>@Api
请求参数缓存
我们在调试接口的时候,有的接口会有很多参数,当我们好不容易填好了所有的参数,由于我们不小心关闭了页面,下次再调试的时候发现还需要再次将参数输入一遍,心态会爆炸吧,所以 knife4j 在文档管理中增加了一个选项:开启请求参数缓存
Tips:
俩种情况会失效
1、 @ApiModelProperty 注解中添加 example (属性的示例值)属性,那么, knife4j 将不会使用缓存,使用的是后端指定的 example
2、当域名发生改变时,所有缓存将会失效
过滤请求参数
我们在开发过程中,经常会遇到这样的一个问题,新增和修改接口,修改接口需要传递修改的记录id,但是新增则不需要,而后端往往会将修改和新增的入参对象设置为一个对象,那么这个对象中必然会存在 id 字段,这就会对新增造成误导
所以,knife4j 支持了请求参数的过滤(忽略),实现方式也是非常的简单,使用自定义增强注解ApiOperationSupport中的ignoreParameters属性,可以强制忽略要显示的参数
这里表单和json格式过滤参数是不一样的
我们先看表单格式
@ApiModel("用户信息")
@Getter
@Setter
@ToString
public class UserDTO {@ApiModelProperty(value = "用户id")private Long id;@ApiModelProperty(value = "用户名",example = "李雷")private String username;@ApiModelProperty(value = "性别",example = "男")private String gender;@ApiModelProperty(value = "手机号码",example = "18888888888")private String phone;@ApiModelProperty(value = "用户收货地址信息")private UserAddressDTO userAddressDTO;
}@Getter
@Setter
@ToString
public class UserAddressDTO {@ApiModelProperty(value = "收获地址的记录id")private Long id;@ApiModelProperty(value = "省")private String province;@ApiModelProperty(value = "市")private String city;@ApiModelProperty(value = "区")private String district;@ApiModelProperty(value = "详细地址")private String addr;
}@PostMapping(value = "/saveUser")@ApiOperation("新增用户信息-表单")@ApiOperationSupport(author = "yolo",ignoreParameters = {"id","userAddressDTO.id"})public String saveUser(UserDTO userDTO){System.out.println("前端传递的用户信息:"+ userDTO);return "save success";}@PostMapping(value = "/updateUser")@ApiOperation("编辑用户信息")@ApiOperationSupport(author = "yolo")public String updateUser( UserDTO userDTO){System.out.println("前端传递的用户信息:"+ userDTO);return "edit success";}
在过滤字段的时候,第一层我们只要填写对象中的属性名即可,但如果需要过滤第二层,根据忽略规则中的第二条,我们在 UserDTO 对象中引入 UserAddressDTO 对象:private UserAddressDTO userAddressDTO; 我们还需要忽略 UserAddressDTO 对象中的 id 属性,那么需要填上 userAddressDTO.id ,其中 userAddressDTO 要与 UserDTO 对象中的 UserAddressDTO 属性名一致
新增操作没有id
编辑操作
JSON格式忽略
专业说法是:实例名.属性名,以新增用户为例,我们需要过滤用户id,那么写法就是:userDTO.id,其中 userDTO 为 saveUser() 的 参数名
@PostMapping(value = "/saveUser")@ApiOperation("新增用户信息")@ApiOperationSupport(author = "yolo",ignoreParameters = {"userDTO.id","userDTO.userAddressDTO.id"})public String saveUser(@RequestBody UserDTO userDTO){System.out.println("前端传递的用户信息:"+ userDTO);return "save success";}
禁用调试
knife4j:enable: truesetting:enableDebug: false
enableDebug:该属性是一个Boolean值,代表是否启用调试功能,默认值为true(代表开启调试),如果要禁用调试,该值设为false
同样,此操作也需要开发者在创建Docket逻辑分组对象时,通过Knife4j提供的工具对象OpenApiExtensionResolver将扩展属性进行赋值
禁用搜索框
发者如果想要禁用Ui界面中的搜索功能,需要通过增强属性进行配置,此功能需要开启增强功能
knife4j:enable: truesetting:enableSearch: false
enableSearch:该属性是一个Boolean值,代表是否启用搜索功能,默认值为true(代表开启搜索),如果要禁用搜索,该值设为false
同样,此操作也需要开发者在创建Docket逻辑分组对象时,通过Knife4j提供的工具对象OpenApiExtensionResolver将扩展属性进行赋值。具体的代码实现请参考禁用调试和自定义主页内容,我这里就不重复了。
相关文章:

SpringBoot 整合knife4j
文章目录SpringBoot 整合knife4j引入knife4j注解案例knife4j增强功能接口添加作者资源屏蔽访问页面加权控制接口排序分组排序请求参数缓存过滤请求参数禁用调试禁用搜索框SpringBoot 整合knife4j Knife4j是一款基于Swagger 2的在线API文档框架 在Spring Boot中,使…...

73-归并排序练习-LeetCode148排序链表
题目 给你链表的头结点 head ,请将其按升序排列并返回排序后的链表 。 示例 1: 输入:head [4,2,1,3] 输出:[1,2,3,4] 示例 2: 输入:head [-1,5,3,4,0] 输出:[-1,0,3,4,5] 示例 3ÿ…...
Hystrix学习笔记
Hystrix 官方文档: https://github.com/Netflix/Hystrix/wiki 是什么 In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed …...

面向对象编程(基础)8:关键字:package、import
目录 8.1 package(包) 8.1.1 语法格式 说明: 8.1.2 包的作用 8.1.3 应用举例 举例2:MVC设计模式 8.1.4 JDK中主要的包介绍 8.2 import(导入) 8.2.1 语法格式 8.2.2 应用举例 8.2.3 注意事项 8.1 package(包) package,称为包&#x…...

【机器学习】P10 从头到尾实现一个线性回归案例
这里写自定义目录标题(1)导入数据(2)画出城市人口与利润图(3)计算损失值(4)计算梯度下降(5)开始训练(6)画出训练好的模型(…...

【Java EE】-多线程编程(四) 死锁
作者:学Java的冬瓜 博客主页:☀冬瓜的主页🌙 专栏:【JavaEE】 分享:2023.3.31号骑行的照片再发一次(狗头)。 主要内容:什么是死锁?不可重入可重入、死锁的三个典型情况:1、一个线程一…...
学习数据结构第1天(数据结构的基本概念)
数据结构的基本概念基本概念和术语数据结构的三要素经典试题基本概念和术语 1.数据 数据是信息的载体,是描述客观事物属性的数、字符以及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 2.数据元素 数据元素是数据的基本…...
南大通用数据库-Gbase-8a-学习-33-空洞率查询与解决方法
目录 一、个人理解 二、存储过程 三、虚机测试 四、解决方法 1、重建表 2、shrink space 一、个人理解 空洞率的产生是由于delete语句并不会真实的删除数据,只是在数据上打了一个不可见标签,但实际还是占用着相应的存储空间。 二、存储过程 自定义…...

为什么我们认为GPT是一个技术爆炸
从23年初,ChatGPT火遍全球,通过其高拟人化的回答模式,大幅提升了人机对话的体验和效率,让用户拥有了一个拥有海量知识的虚拟助手,根据UBS发布的研究报告显示,ChatGPT在1月份的月活跃用户数已达1亿ÿ…...

程序员如何能提高自己的编程水平?
这些实用的小建议,能帮你迅速地提高编程水平: 不要做无意义的奋斗 拒绝喊口号和无意义的奋斗,包括但不限于: ①做了计划表却从未有执行的一天; ②每天都是最早来、最晚走,但是工作进度趋近于0;…...

从零使用vuepress搭建个人博客部署.github.io
前言 记录小白如何搭建个人博客 github部署的博客👉: DreamLuffe的博客 netilify部署的博客:👉:DreamLuffe的博客 个人博客搭建实战 网上有很多优秀的开源博客页面,我们就直接安装好,再继续…...

Python 进阶指南(编程轻松进阶):十一、注释、文档字符串和类型提示
原文:http://inventwithpython.com/beyond/chapter11.html 源代码中的注释和文档可能和代码一样重要。原因是软件是永远不会完成的;无论是添加新功能还是修复错误,您总是需要做出改变。但是你不能改变代码,除非你理解它࿰…...

python item()方法
Python中有很多方法来解决一些简单的问题,其中最常见的就是用 item ()方法来完成。item ()方法的全称是item-process (),该方法用来对对象进行创建、删除、改变、添加、更新等操作。…...

【day2】Android Jetpack Compose环境搭建
【day2】Android Jetpack Compose环境搭建 以下是适用于 Jetpack Compose 的环境要求: Android Studio 版本:4.2 Canary 15 或更高版本Gradle 版本:7.0.0-beta02 或更高版本Android 插件版本:4.2.0-beta15 或更高版本Kotlin 版本…...

stable-diffusion安装和简单测试
参考: https://github.com/CompVis/stable-diffusion 理解DALLE 2, Stable Diffusion和 Midjourney的工作原理 Latent Diffusion Models论文解读 【生成式AI】淺談圖像生成模型 Diffusion Model 原理 【生成式AI】Stable Diffusion、DALL-E、Imagen 背後…...
MATLAB算法实战应用案例精讲-【智能优化算法】 基于帕累托包络的选择算法II(PESA-II)(附MATLAB代码实现)
目录 前言 知识储备 数据包络分析(DEA) 特点 名词解释 类型介绍 案例简介 软件操作(SPSSPRO)...

【华为机试真题详解JAVA实现】—坐标移动
目录 一、题目描述 二、解题代码 一、题目描述 开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。 输入: 合法坐标为A(或者D或者W或者S) +…...

【软考五】数据库(做题)
该文章不适合学习数据库,适合考证,遇到实际问题的,不要在这儿浪费时间。切记切记 软考之数据库一、概念数据模型(下午题常考)二、结构数据模型关系模型1、关系模型中基本术语2、关系模型中的关系完整性约束3、关系代数…...

【Java Web】012 -- SpringBootWeb综合案例(登录功能、登录校验、异常处理)
目录 一、登录功能 1、基础登录功能 ①、SQL语句 ②、接口参数 ③、实现思路 ④、实现步骤 2、联调Bug(没有Cookie或Session) 二、登录校验 1、登录校验的实现思路 2、会话技术 ①、会话与会话跟踪 ②、会话跟踪方案对比 Cookie Session …...
跨界智能手表:比亚迪向左,小鹏向右
如今,电动化、智能化是汽车行业转型的大方向,而由于目前国内汽车产业在电动化方面已经算是“小有成效”,因此,抢占智能化高地,打造一个多设备互融的生态系统,就成为了车企的共同愿景。在此背景下࿰…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...