Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the visualization of Go Module dependency relationship

2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to achieve the visualization of Go Module dependencies". In daily operation, I believe many people have doubts about how to achieve the visualization of Go Module dependencies. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful for you to answer the doubts of "how to achieve the visualization of Go Module dependencies". Next, please follow the editor to study!

Recently, I developed a very simple gadget with a total code volume of less than 200 lines. Today, a brief introduction to it. What kind of tool is this? It is a tool for visualizing Go Module dependencies.

Why to develop

Why would you want to develop this tool? There are two main reasons:

First, we often see people talking about Go Module in the community recently. So I also spent some time studying it. During that time, I encountered a requirement on how to clearly identify the relationship between dependencies in the module. After some understanding, I found go mod graph.

The effect is as follows:

$go mod graphgithub.com/poloxue/testmod golang.org/x/text@v0.3.2github.com/poloxue/testmod rsc.io/quote/v3@v3.1.0github.com/poloxue/testmod rsc.io/sampler@v1.3.1golang.org/x/text@v0.3.2 golang.org/x/tools@v0.0.0-20180917221912-90fa682c2a6ersc.io/quote/v3@v3.1.0 rsc.io/sampler@v1.3.0rsc.io/sampler@v1.3. 1 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0crsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c

The format of each line is module dependent module, which can basically meet the requirements, but it still doesn't feel so intuitive.

Second, I had a project in hand, and dep was always used in package management. So I learned about it and read the official documents carefully. One of the chapters describes how to visualize dependencies.

The package diagram given in the document:

When I saw this picture, my eyes lit up instantly, the graphics were excellent, and the relationship between different dependencies was clear at a glance. Isn't that what I want? 666, like it.

But the problem that comes with it is that go mod doesn't have the ability. What shall I do?

How to realize

Let's see if someone has already done it. I searched the Internet, but I couldn't find it. Can it be realized by itself? We should be able to learn from dep's ideas, right?

Here's how dep relies on visualization:

# linux$ sudo apt-get install graphviz$ dep status-dot | dot-T png | display# macOS$ brew install graphviz$ dep status-dot | dot-T png | open-f-a / Applications/Preview.app# Windows > choco install graphviz.portable > dep status-dot | dot-T png-o status.png; start status.png

This shows how to use the three major systems, all of which have installed a software package, graphviz. Judging from the name, this should be a software used to achieve visualization, that is, to draw pictures. This is also the case, you can take a look at its official website.

Looking at its use again, it is found that it is all through the combination of pipeline commands, and the previous parts are basically the same, which are all dep status-dot | dot-T png. The latter part is different in different systems, Linux is display,MacOS is open-f-a / Applications/Preview.app,Window is start status.png.

After a little analysis, we will understand that the front is to generate the picture, and the back is to display the picture. Because the picture display commands are different in different systems, the latter part is also different.

Now the focus is on the previous, that is, dep status-dot | what does dot-T png do, and how on earth does it achieve drawing? A rough guess is that dot-T png is generated by data provided by dep status-dot. Let's take a look at the implementation of dep status-dot.

$dep status-dotdigraph {node [shape=box]; 2609291568 [label= "github.com/poloxue/hellodep"]; 953278068 [label= "rsc.io/quote\ nv3.1.0"]; 3852693168 [label= "rsc.io/sampler\ nv1.0.0"]; 2609291568-> 953278068; 953278068-> 3852693168;}

At first glance, the output is a piece of code that looks like you don't know what it is, which is supposed to be the language that graphviz uses to draw charts. Do you still have to study? Of course not, it's very simple to use here, just apply it directly.

Try to analyze it, the first two lines can be ignored, this should be a specific way of writing graphviz, indicating what kind of picture to draw. Our main concern is how to provide the data in the correct form.

2609291568 [label= "github.com/poloxue/hellodep"]; 953278068 [label= "rsc.io/quote\ nv3.1.0"]; 3852693168 [label= "rsc.io/sampler\ nv1.0.0"]; 2609291568-> 953278068 Taiwan 953278068-> 3852693168

At a glance, you can see that there are two structures, one is to associate ID for dependencies, and the other is to express the relationship between dependencies through ID and->.

According to the above guess, we can try to draw a simple diagram to show that module a depends on module b. Execute the command as follows, and send the drawing code to the dot command through the each pipeline.

$echo 'digraph {node [shape=box]; 1 [label= "a"]; 2 [label= "b"]; 1-> 2;}' | dot-T png | open-f-a / Applications/Preview.app

The effect is as follows:

It's so easy to draw a dependency graph.

Seeing here, do you find that the problem has become very simple? We only need to convert the output of go mod graph into a similar structure to achieve visualization.

Introduction to the development process

Next, develop this Mini Program. I named this Mini Program modv, which means module visible. The project source code is located in poloxue/modv.

Receive input from the pipeline

First check whether the data input pipeline is normal.

Our goal is to use a method similar to mapping in dep, where go mod graph passes data to modv through pipes. Therefore, first check the os.Stdin, that is, check whether the standard input status is normal, and whether it is a pipeline transmission.

Here is the code for the main function, which is located in main.go.

Func main () {info, err: = os.Stdin.Stat () if err! = nil {fmt.Println ("os.Stdin.Stat:" Err) PrintUsage () os.Exit (1)} / / is it a pipeline transmission if info.Mode () & os.ModeNamedPipe = = 0 {fmt.Println ("command err: command is intended to work with pipes.") PrintUsage () os.Exit (1)}

Once we have confirmed that the input device is all right, we can enter the process of data reading, parsing, and rendering.

Mg: = NewModuleGraph (os.Stdin) mg.Parse () mg.Render (os.Stdout)}

Next, let's take a specific look at how to implement the data processing flow.

Abstract implementation structure

First define a structure and roughly define the entire process.

Type ModGraph struct {Reader io.Reader / / read data stream} func NewModGraph (r io.Reader) * ModGraph {return & ModGraph {Reader: r}} / / perform data processing conversion func (m * ModGraph) Parse () error {} / / result rendering and output func (m * ModGraph) Render (w io.Writer) error {}

Take a look at the output of go mod graph again, as follows:

Github.com/poloxue/testmod golang.org/x/text@v0.3.2github.com/poloxue/testmod rsc.io/quote/v3@v3.1.0...

The structure of each line is a module dependency. The goal now is to parse it into the following structure:

Digraph {node [shape=box]; 1 github.com/poloxue/testmod; 2 golang.org/x/text@v0.3.2; 3 rsc.io/quote/v3@v3.1.0; 1-> 2; 1-> 3;}

As mentioned earlier, there are two different structures, namely, the association between the module and ID, and the module ID represents the dependency association between modules. Add two members to the ModGraph structure to represent them.

Type ModGraph struct {r io.Reader / / data stream read instance, where os.Stdin / / mapping of each item name to ID [string] int / / ID and dependency ID relation mapping, an ID may depend on multiple items Dependencies map [int] [] int}

Note that after adding two map members, remember to initialize them in NewModGraph.

Mod graph output parsing

How to parse?

At the end of the introduction, the goal is very clear. This is to parse the input data into two members, Mods and Dependencies, with the implementation code in the Parse method.

To facilitate data reading, first, we create a new bufReader based on reader using bufio

Func (m * ModGraph) Parse () error {bufReader: = bufio.NewReader (m.Reader).

To make it easier to parse the data by row, we loop through the ReadBytes () method of bufReader to read the data in os.Stdin one line at a time. Then, each row of data is segmented by spaces to get the two items of the dependency. The code is as follows:

For {relationBytes, err: = bufReader.ReadBytes ('\ n') if err! = nil {if err = = io.EOF {return nil} return err} relation: = bytes.Split (relationBytes, [] byte (")) / / module and dependency mod, depMod: = strings.TrimSpace (string (relation [0])) Strings.TrimSpace (string (relation [1]))...}

The next step is to organize the parsed dependencies into Mods and Dependencies members. Module ID is the simplest way to generate rules, incrementing from 1. The implementation code is as follows:

ModId, ok: = m.Mods [mod] if! ok {modId = serialID m.Mods [mod] = modId serialID + = 1} depModId, ok: = m.Mods [depMod] if! ok {depModId = serialID m.Mods [depMod] = depModId serialID + = 1} if _, ok: = m.Dependencies [modId] Ok {m.Dependencies [modId] = append (m.Dependencies [modId], depModId)} else {m.Dependencies [modId] = [] int {depModId}}

The work of parsing is over here.

Render the result of parsing

This gadget still has one last step to do, which is to render the parsed data to meet the mapping requirements of the graphviz tool. The implementation code is the Render part:

First, define a template to generate an output format that meets the requirements.

Var graphTemplate = `digraph {node [shape=box]; {{range $mod, $modId: = .mods -}} {{$modId}} [label= "{{$mod}}"]; {{end -}} {{- range $modId, $depModIds: = .dependencies -}} {{- range $_, $depModId: = $depModIds -} {{$modId}-> {{$depModId}; {{end -}} {{- end -}`

There is nothing to introduce in this section, mainly to be familiar with the syntax specification of the text/template template in Go. In order to show friendliness, the removal of line breaks is achieved here, which does not affect reading as a whole.

Next, look at the implementation of the Render method, and put the previously parsed Mods and Dependencies into the template for rendering.

Func (m * ModuleGraph) Render (w io.Writer) error {templ, err: = template.New ("graph") .Parse (graphTemplate) if err! = nil {return fmt.Errorf ("templ.Parse:% v", err)} if err: = templ.Execute (w, map [string] interface {} {"mods": m.Mods "dependencies": m.Dependencies,}) Err! = nil {return fmt.Errorf ("templ.Execute:% v", err)} return nil}

Now, all the work has been finished. Finally, integrate the process into the main function. The next step is to use.

user's experience

Let's experience it. In addition, I have only tested the use of this tool under Mac. If you have any questions, please feel free to raise them.

First of all, to install graphviz, the installation method has been introduced at the beginning of this article, choose your system installation method.

The next step is to install modv with the following command:

$go get github.com/poloxue/modv

Installation complete! Simply test its use.

Take MacOS as an example. First download the test library, github.com/poloxue/testmod. Go to the testmod directory and execute the command:

$go mod graph | modv | dot-T png | open-f-a / Applications/Preview.app

If the execution is successful, you will see the following effect:

It perfectly demonstrates the dependencies between the various modules.

Some thoughts

This article is a practical article that presents a tool that can be used from a simple idea to success. Although, the development is not difficult, from development to completion, only took an hour or two. But in my opinion, this is indeed a tool of practical value.

There are also some ideas that have not been implemented and verified, such as whether it is convenient to display the dependency tree of a given node rather than the whole project once the project is large. Also, whether this gadget can generate some value when other projects migrate to Go Module.

At this point, the study on "how to visualize Go Module dependencies" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report