feat(Go-Tool):

2020/12/31:新增项目案例(角色技能树)
               2020/12/31: 修改diliver包结构
This commit is contained in:
Huangzj
2020-12-31 14:25:25 +08:00
parent 84b5787dd8
commit f3c056f84e
23 changed files with 738 additions and 9 deletions
@@ -0,0 +1,32 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 17:39
* @Description
*/
package SkillTopology
import (
"Go-Tool/ProgressTest/SkillTopology/model"
"fmt"
"testing"
)
func TestDrawSkill(t *testing.T) {
topology := GetCounsellorSkillByDb(NewSkilledWorker(), model.CounsellorId)
DealWithUnLockSkill(topology)
}
func TestUpdateSkill(t *testing.T) {
//测试一个没有达到升级条件的节点7
topology := GetCounsellorSkillByDb(NewSkilledWorker(), model.CounsellorId)
ok := CheckSkillUpdate(topology, 7)
fmt.Println(fmt.Sprintf("技能7是否满足升级条件:%v", ok))
//测试一个可以升级的节点:11
ok = CheckSkillUpdate(topology, 11)
fmt.Println(fmt.Sprintf("技能11是否满足升级条件:%v", ok))
}
+19
View File
@@ -0,0 +1,19 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 17:25
* @Description:业务场景
*/
package SkillTopology
import "Go-Tool/ProgressTest/SkillTopology/model"
//获取根据大臣的数据获取一个大臣对应的技能树拓扑的等级对应关系
func GetCounsellorSkillByDb(worker *SkilledWorker, counsellorId int) *model.Topology {
counsellor := worker.CounsellorSrv.GetCounsellorSkill(counsellorId)
//根据大臣Id获取大臣技能树拓扑
topology := SkillTopologyMap[counsellorId]
//根据大臣当前等级信息,组合技能树技能等级
topology = MakeSimulationSkillsWithLevel(topology, counsellor.Skill)
return topology
}
@@ -0,0 +1,151 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 14:22
* @Description:模拟的一个大臣的技能树拓扑关系
*/
package SkillTopology
import "Go-Tool/ProgressTest/SkillTopology/model"
type NodeRelation struct {
ParentId int
ChildrenId []int
}
var (
//拓扑父子关系,模拟读配置
topologyConfig = map[int][]int{
1: {2, 3, 4},
2: {8},
3: {5, 6},
4: {10, 11},
5: {7},
6: {7},
8: {9},
10: {12},
11: {12},
}
headNodeId = 1
)
//模拟其中一个大臣获取技能拓扑
func SimulationParamGetTopology(worker *SkilledWorker) *model.Topology {
//模拟获取技能链
skill1 := SimulationSkills(worker)
//拓扑父关系
skill1 = BackSteppingHeadWithChildren(skill1)
topology := &model.Topology{
HeadSkillNode: skill1,
CounsellorId: model.CounsellorId,
SkillIdMap: GetTopologyHeadMap(skill1), //获取技能Id和节点的对应关系,方便查找
}
return topology
}
func SimulationSkills(worker *SkilledWorker) *model.SkillNode {
//根节点技能
skill1 := &model.SkillNode{
SkillId: 1,
SkillFunc: worker.SkillId1,
Parent: nil, //第一个技能的父节点应该是空的
}
skill2 := model.SkillNode{
SkillId: 2,
SkillFunc: worker.SkillId2,
}
skill3 := model.SkillNode{
SkillId: 3,
SkillFunc: worker.SkillId3,
}
skill4 := model.SkillNode{
SkillId: 4,
SkillFunc: worker.SkillId4,
}
skill5 := model.SkillNode{
SkillId: 5,
SkillFunc: worker.SkillId5,
}
skill6 := model.SkillNode{
SkillId: 6,
SkillFunc: worker.SkillId6,
}
skill7 := model.SkillNode{
SkillId: 7,
SkillFunc: worker.SkillId7,
}
skill8 := model.SkillNode{
SkillId: 8,
SkillFunc: worker.SkillId8,
}
skill9 := model.SkillNode{
SkillId: 9,
SkillFunc: worker.SkillId9,
}
skill10 := model.SkillNode{
SkillId: 10,
SkillFunc: worker.SkillId10,
}
skill11 := model.SkillNode{
SkillId: 11,
SkillFunc: worker.SkillId11,
}
skill12 := model.SkillNode{
SkillId: 12,
SkillFunc: worker.SkillId12,
}
skillMap := map[int]*model.SkillNode{
1: skill1,
2: &skill2,
3: &skill3,
4: &skill4,
5: &skill5,
6: &skill6,
7: &skill7,
8: &skill8,
9: &skill9,
10: &skill10,
11: &skill11,
12: &skill12,
}
//拓扑父子关系
return MakeTopologyByConfig(skillMap, topologyConfig, headNodeId)
}
func MakeTopologyByConfig(nodes map[int]*model.SkillNode, config map[int][]int, headNodeId int) *model.SkillNode {
headNode := nodes[headNodeId]
if headNode == nil {
return nil
}
for nodeId, childrenId := range config {
childrenNodes := make([]*model.SkillNode, 0)
for _, childId := range childrenId {
if node := nodes[childId]; node != nil {
childrenNodes = append(childrenNodes, node)
}
}
nodes[nodeId].Children = childrenNodes
}
return headNode
}
//组装技能所对应的Map节点
func MakeSimulationSkillsWithLevel(topology *model.Topology, skillList []*model.Skill) *model.Topology {
if topology == nil || topology.HeadSkillNode == nil || len(skillList) == 0 {
return topology
}
skillIdMap := topology.SkillIdMap
for _, skill := range skillList {
if v, ok := skillIdMap[skill.Id]; ok {
v.Level = skill.Level
skillIdMap[skill.Id] = v
}
}
return topology
}
+79
View File
@@ -0,0 +1,79 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 14:21
* @Description
*/
package SkillTopology
import (
"Go-Tool/ProgressTest/SkillTopology/dbOperation"
"fmt"
)
type Session int
type SkilledWorker struct {
TX Session //在实际的程序中,这个地方应该是事务,这边示例只用int暂且表示^_^
CounsellorSrv *dbOperation.CounsellorSrv //在实际的程序中,这个地方是大臣的Srv,以此从数据库中获取大臣信息,这边示例只用int暂且表示
SkillPointSrv *dbOperation.SkillPointSrv //在实际的程序中,这个地方应该是技能点的Srv,以此获得数据库数据,这边示例只用int暂且表示
//...... 其他相关的属性srv
}
func NewSkilledWorker() *SkilledWorker {
return &SkilledWorker{
TX: 0,
CounsellorSrv: dbOperation.NewCounsellorSrv(),
SkillPointSrv: dbOperation.NewSkillPointSrv(),
}
}
//这边的技能模拟对应实际技能,示例只做输出
func (*SkilledWorker) SkillId1() {
fmt.Println("我是技能1")
}
func (*SkilledWorker) SkillId2() {
fmt.Println("我是技能2")
}
func (*SkilledWorker) SkillId3() {
fmt.Println("我是技能3")
}
func (*SkilledWorker) SkillId4() {
fmt.Println("我是技能4")
}
func (*SkilledWorker) SkillId5() {
fmt.Println("我是技能5")
}
func (*SkilledWorker) SkillId6() {
fmt.Println("我是技能6")
}
func (*SkilledWorker) SkillId7() {
fmt.Println("我是技能7")
}
func (*SkilledWorker) SkillId8() {
fmt.Println("我是技能8")
}
func (*SkilledWorker) SkillId9() {
fmt.Println("我是技能9")
}
func (*SkilledWorker) SkillId10() {
fmt.Println("我是技能10")
}
func (*SkilledWorker) SkillId11() {
fmt.Println("我是技能11")
}
func (*SkilledWorker) SkillId12() {
fmt.Println("我是技能12")
}
@@ -0,0 +1,22 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 15:46
* @Description
*/
package SkillTopology
import "Go-Tool/ProgressTest/SkillTopology/model"
var SkillTopologyMap map[int]*model.Topology
func GetSkillTopologyMapById(counsellorId int) *model.Topology {
return SkillTopologyMap[counsellorId]
}
func init() {
SkillTopologyMap = make(map[int]*model.Topology, 0)
SkillTopologyMap[model.CounsellorId] = SimulationParamGetTopology(NewSkilledWorker())
//....下面是不同大臣的初始化技能树链
}
+145
View File
@@ -0,0 +1,145 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 16:20
* @Description:拓扑工具
*/
package SkillTopology
import "Go-Tool/ProgressTest/SkillTopology/model"
//设置技能提升,执行对应的方法
func SkillUpdate(topology *model.Topology, skillId int) {
//如果技能满足提升的条件
if CheckSkillUpdate(topology, skillId) {
skill := topology.SkillIdMap[skillId]
skill.Level = skill.Level + 1
//执行技能方法
skill.SkillFunc()
//更新节点信息
topology.SkillIdMap[skillId] = skill
//刷新对应父节点的属性
RefreshParent(skill)
//刷新对应子节点的属性
RefreshChildren(skill)
return
}
panic("技能未达到解锁要求")
}
//当技能发生变化的时候,刷新父节点对应的该技能的属性
func RefreshParent(skill *model.SkillNode) {
for _, parent := range skill.Parent {
children := make([]*model.SkillNode, 0)
for _, child := range parent.Children {
if child.SkillId != skill.SkillId {
children = append(children, child)
} else {
children = append(children, skill)
}
}
parent.Children = children
}
}
//当技能发生变化的时候,刷新子节点对应的技能的属性
func RefreshChildren(skill *model.SkillNode) {
for _, child := range skill.Children {
parent := make([]*model.SkillNode, 0)
for _, p := range child.Parent {
if child.SkillId != skill.SkillId {
parent = append(parent, p)
} else {
parent = append(parent, skill)
}
}
child.Parent = parent
}
}
//校验技能升级是否合法
func CheckSkillUpdate(topology *model.Topology, skillId int) bool {
skill := topology.SkillIdMap[skillId]
if topology == nil || topology.HeadSkillNode == nil || skill == nil {
return false
}
//父节点升级,直接返回true
if skill.Parent == nil {
return true
}
for _, parent := range skill.Parent {
if parent.Level == 0 {
return false
}
}
return true
}
//执行所有等级大于0的技能效果
func DealWithUnLockSkill(topology *model.Topology) {
if topology == nil || topology.HeadSkillNode == nil {
return
}
node := topology.HeadSkillNode
travelDealSkillNode(node)
}
//获取技能Id对应的技能节点
func GetTopologyHeadMap(node *model.SkillNode) map[int]*model.SkillNode {
skillIdMap := make(map[int]*model.SkillNode, 0)
if node == nil {
return skillIdMap
}
//头节点的处理
skillIdMap[node.SkillId] = node
//遍历所有的子节点
travelSkillNode(node, skillIdMap)
return skillIdMap
}
//已经设置好子节点属性(Children),反推父节点属性(Parent
func BackSteppingHeadWithChildren(node *model.SkillNode) *model.SkillNode {
if node == nil {
return node
}
//头节点的处理
travelNodeSetParent(node)
return node
}
func travelDealSkillNode(node *model.SkillNode) {
//执行对应的方法
if node.SkillFunc != nil && node.Level > 0 {
node.SkillFunc()
}
//递归遍历所有的子节点
for _, child := range node.Children {
travelDealSkillNode(child)
}
}
func travelNodeSetParent(node *model.SkillNode) {
for _, child := range node.Children {
if child != nil {
//有多个父的情况
if child.Parent != nil || len(child.Parent) != 0 {
child.Parent = append(child.Parent, node)
} else {
child.Parent = []*model.SkillNode{node}
}
//再深入到子节点的内部
travelNodeSetParent(child)
}
}
}
func travelSkillNode(node *model.SkillNode, skillIdMap map[int]*model.SkillNode) {
for _, child := range node.Children {
if child != nil {
skillIdMap[child.SkillId] = child
travelSkillNode(child, skillIdMap)
}
}
}
@@ -0,0 +1,106 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 16:59
* @Description
*/
package SkillTopology
import (
"Go-Tool/ProgressTest/SkillTopology/model"
"fmt"
"testing"
)
//正确的输出应该是:
//SkillId:1,Parent:[],Children:[2 3 4]
//SkillId:2,Parent:[1],Children:[8]
//SkillId:3,Parent:[1],Children:[5 6]
//SkillId:4,Parent:[1],Children:[10 11]
//SkillId:5,Parent:[3],Children:[7]
//SkillId:6,Parent:[3],Children:[7]
//SkillId:10,Parent:[4],Children:[12]
//SkillId:11,Parent:[4],Children:[12]
//SkillId:8,Parent:[2],Children:[9]
//SkillId:9,Parent:[8],Children:[]
//SkillId:12,Parent:[10 11],Children:[]
//SkillId:7,Parent:[5 6],Children:[]
func TestGetTopologyHeadMap(t *testing.T) {
worker := NewSkilledWorker()
skill1 := SimulationSkills(worker)
//拓扑父关系
skill1 = BackSteppingHeadWithChildren(skill1)
for _, skill := range GetTopologyHeadMap(skill1) {
var pId []int
for _, p := range skill.Parent {
pId = append(pId, p.SkillId)
}
var cId []int
for _, c := range skill.Children {
cId = append(cId, c.SkillId)
}
fmt.Println(fmt.Sprintf("SkillId:%v,Parent:%v,Children:%v", skill.SkillId, pId, cId))
}
}
//正确的输出应该是:
//SkillId:1,Parent:[]
//SkillId:2,Parent:[1]
//SkillId:3,Parent:[1]
//SkillId:4,Parent:[1]
//SkillId:5,Parent:[3]
//SkillId:6,Parent:[3]
//SkillId:11,Parent:[4]
//SkillId:10,Parent:[4]
//SkillId:8,Parent:[2]
//SkillId:9,Parent:[8]
//SkillId:7,Parent:[5 6]
//SkillId:12,Parent:[10 11]
func TestBackSteppingHeadWithChildren(t *testing.T) {
worker := NewSkilledWorker()
skill1 := SimulationSkills(worker)
//拓扑父关系
skill1 = BackSteppingHeadWithChildren(skill1)
for _, skill := range GetTopologyHeadMap(skill1) {
var pId []int
for _, p := range skill.Parent {
pId = append(pId, p.SkillId)
}
fmt.Println(fmt.Sprintf("SkillId:%v,Parent:%v", skill.SkillId, pId))
}
}
//正确的输出为:
//
//我是技能11
//父节点Id为4,对应的Update的子节点的Id为:11,Level为:4
//子节点Id为12,对应的Update的父节点的Id为:11,Level为:4
func TestSkillUpdate(t *testing.T) {
topology := GetCounsellorSkillByDb(NewSkilledWorker(), model.CounsellorId)
SkillUpdate(topology, 11)
for _, skill := range GetTopologyHeadMap(topology.HeadSkillNode) {
for _, child := range skill.Children {
if child.SkillId == 11 {
fmt.Println(fmt.Sprintf("父节点Id为%v,对应的Update的子节点的Id为:%v,Level为:%v", skill.SkillId, child.SkillId, child.Level))
}
}
for _, p := range skill.Parent {
if p.SkillId == 11 {
fmt.Println(fmt.Sprintf("子节点Id为%v,对应的Update的父节点的Id为:%v,Level为:%v", skill.SkillId, p.SkillId, p.Level))
}
}
}
}
@@ -0,0 +1,28 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 14:49
* @Description
*/
package dbOperation
import (
"Go-Tool/ProgressTest/SkillTopology/model"
)
type CounsellorSrv struct {
}
func NewCounsellorSrv() *CounsellorSrv {
return &CounsellorSrv{}
}
//通过模拟的Id来获取对应的技能
func (*CounsellorSrv) GetCounsellorSkill(counsellorId int) *model.Counsellor {
skillPoint := NewSkillPointSrv()
return &model.Counsellor{
Id: model.CounsellorId,
Name: "测试的大臣",
Skill: skillPoint.GetAllSkillByCounsellorId(model.CounsellorId),
}
}
@@ -0,0 +1,38 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 14:48
* @Description
*/
package dbOperation
import (
"Go-Tool/ProgressTest/SkillTopology/model"
"Go-Tool/util/file"
"encoding/json"
)
type SkillPointSrv struct {
//.... 需要的所有属性
}
func NewSkillPointSrv() *SkillPointSrv {
return &SkillPointSrv{}
}
func (*SkillPointSrv) RacePoint() {
}
type tmp struct {
Skills []*model.Skill
}
//模拟数据,未激活的技能(Level = 0 )技能设置为:6、7、8、10、12,其他为激活的技能,没有等级的技能在数据库不体现
func (*SkillPointSrv) GetAllSkillByCounsellorId(counsellorId int) []*model.Skill {
var tmp tmp
content, _ := file.ReadJsonFile("F://Go_BySelf//src//Go-Tool//ProgressTest//SkillTopology//skill.json")
_ = json.Unmarshal([]byte(content), &tmp)
return tmp.Skills
}
@@ -0,0 +1,19 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 15:08
* @Description
*/
package model
type Counsellor struct {
Id int
Name string
Skill []*Skill
}
type Skill struct {
Id int
Level int
Description string
}
@@ -0,0 +1,11 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 15:56
* @Description:模拟数据
*/
package model
const (
CounsellorId = 10
)
@@ -0,0 +1,16 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 15:00
* @Description:技能树节点
*/
package model
type SkillNode struct {
SkillId int //技能Id,对应数据库技能Id字段 和 Skiller技能func
Parent []*SkillNode //对应父关系节点,根节点是nil
Children []*SkillNode //对应子关系节点,没有则为nil
Level int //技能等级,通过技能等级判断该技能是否解锁,省去UnLock字段
SkillFunc func() //技能节点对应的技能提升效果
}
@@ -0,0 +1,13 @@
/*
* @Author : huangzj
* @Time : 2020/12/29 15:52
* @Description
*/
package model
type Topology struct {
HeadSkillNode *SkillNode //拓扑头结点
CounsellorId int //拓扑对应的大臣Id
SkillIdMap map[int]*SkillNode //技能ID对应的技能节点,方便查找
}
+9
View File
@@ -0,0 +1,9 @@
##情景说明
程序需要实现对应的大臣对应的技能树功能,技能树解锁有前置条件,在程序启动的时候,对所有该大臣技能进行执行。
可支持技能升级等.
这边只是简单的设计通过一个类似拓扑的方式来处理大臣技能的框架。
![image](技能树说明.jpg)
+39
View File
@@ -0,0 +1,39 @@
{
"Skills": [
{
"Id": 1,
"Level": 1,
"Description": "技能1"
},
{
"Id": 2,
"Level": 1,
"Description": "技能2"
},
{
"Id": 3,
"Level": 1,
"Description": "技能3"
},
{
"Id": 4,
"Level": 1,
"Description": "技能4"
},
{
"Id": 5,
"Level": 1,
"Description": "技能5"
},
{
"Id": 9,
"Level": 1,
"Description": "技能9"
},
{
"Id": 11,
"Level": 3,
"Description": "技能11"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

@@ -4,7 +4,7 @@
* @Description * @Description
*/ */
package ProgressTest package diliver
import ( import (
"Go-Tool/util/file" "Go-Tool/util/file"
@@ -23,7 +23,7 @@ type Deliver struct {
func MakeData() DeliverList { func MakeData() DeliverList {
var deliver DeliverList var deliver DeliverList
content, _ := file.ReadJsonFile("F:\\Go_BySelf\\src\\Go-Tool\\ProgressTest\\deliverData.json") content, _ := file.ReadJsonFile("F:\\Go_BySelf\\src\\Go-Tool\\ProgressTest\\diliver\\deliverData.json")
_ = json.Unmarshal([]byte(content), &deliver) _ = json.Unmarshal([]byte(content), &deliver)
return deliver return deliver
} }
@@ -4,7 +4,7 @@
* @Description * @Description
*/ */
package ProgressTest package diliver
import ( import (
"Go-Tool/util/rand" "Go-Tool/util/rand"
@@ -4,7 +4,7 @@
* @Description在工程中有一个需求是对 指定数量的数组进行划分按照每一层的规则分成对应数量这边做一个测试.(这种方式写的代码太麻烦了直接废弃后面有机会再弄) * @Description在工程中有一个需求是对 指定数量的数组进行划分按照每一层的规则分成对应数量这边做一个测试.(这种方式写的代码太麻烦了直接废弃后面有机会再弄)
*/ */
package ProgressTest package diliver
import ( import (
"Go-Tool/util/rand" "Go-Tool/util/rand"
@@ -4,7 +4,7 @@
* @Description * @Description
*/ */
package ProgressTest package diliver
import "github.com/ahmetb/go-linq" import "github.com/ahmetb/go-linq"
-2
View File
@@ -39,7 +39,5 @@ gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+6 -2
View File
@@ -58,8 +58,6 @@
2020/11/16:新增项目案例(按照一定规则对一组数据进行排序分组) 2020/11/16:新增项目案例(按照一定规则对一组数据进行排序分组)
2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组)
2020/11/25:完善linq包使用示例 2020/11/25:完善linq包使用示例
2020/12/7 :更新bit位操作工作 BitTool 2020/12/7 :更新bit位操作工作 BitTool
@@ -72,9 +70,15 @@
2020/12/16: 添加YAML和结构体转换工具 2020/12/16: 添加YAML和结构体转换工具
2020/12/31:新增项目案例(角色技能树)
# 修复日志 # 修复日志
2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组)
2020/12/16 修复bitStore越位溢出的问题 2020/12/16 修复bitStore越位溢出的问题
2020/12/31: 修改diliver包结构
# mod vendor模式加载包 # mod vendor模式加载包
通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到 通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到