golang AST语法树解析

news2024/9/23 1:26:41

1. 源码示例

package main

import (
	"context"
)

// Foo 结构体
type Foo struct {
	i int
}

// Bar 接口
type Bar interface {
	Do(ctx context.Context) error
}

// main方法
func main() {
	a := 1
}

2. Golang中的AST

golang官方提供的几个包,可以帮助我们进行AST分析:

  • go/scanner:词法解析,将源代码分割成一个个token

  • go/token:token类型及相关结构体定义

  • go/ast:ast的结构定义

    • ast的各种结构定义入口在go/ast/ast.go
  • go/parser:语法分析,读取token流生成ast

通过上述的四个库,我们就可以实现golang代码的语法树分析

3. 使用main.go解析demo.go的AST树

package main

import (
	"go/ast"
	"go/parser"
	"go/token"
	"log"
	"path/filepath"
)

func main() {
	fset := token.NewFileSet()
	// 这里取绝对路径,方便打印出来的语法树可以转跳到编辑器
	path, _ := filepath.Abs("./demo.go")
	f, err := parser.ParseFile(fset, path, nil, parser.AllErrors)
	if err != nil {
		log.Println(err)
		return
	}
	// 打印语法树
	ast.Print(fset, f)
}

3.1. 解析的结果如下

可在http://goast.yuroyoro.net/里贴上源代码后查看

*ast.File {
     1  .  Package: 1:1
     2  .  Name: *ast.Ident {
     3  .  .  NamePos: 1:9
     4  .  .  Name: "main"
     5  .  }
     6  .  Decls: []ast.Decl (len = 4) {
     7  .  .  0: *ast.GenDecl {
     8  .  .  .  TokPos: 3:1
     9  .  .  .  Tok: import
    10  .  .  .  Lparen: 3:8
    11  .  .  .  Specs: []ast.Spec (len = 1) {
    12  .  .  .  .  0: *ast.ImportSpec {
    13  .  .  .  .  .  Path: *ast.BasicLit {
    14  .  .  .  .  .  .  ValuePos: 4:2
    15  .  .  .  .  .  .  Kind: STRING
    16  .  .  .  .  .  .  Value: "\"context\""
    17  .  .  .  .  .  }
    18  .  .  .  .  .  EndPos: -
    19  .  .  .  .  }
    20  .  .  .  }
    21  .  .  .  Rparen: 5:1
    22  .  .  }
    23  .  .  1: *ast.GenDecl {
    24  .  .  .  TokPos: 8:1
    25  .  .  .  Tok: type
    26  .  .  .  Lparen: -
    27  .  .  .  Specs: []ast.Spec (len = 1) {
    28  .  .  .  .  0: *ast.TypeSpec {
    29  .  .  .  .  .  Name: *ast.Ident {
    30  .  .  .  .  .  .  NamePos: 8:6
    31  .  .  .  .  .  .  Name: "Foo"
    32  .  .  .  .  .  .  Obj: *ast.Object {
    33  .  .  .  .  .  .  .  Kind: type
    34  .  .  .  .  .  .  .  Name: "Foo"
    35  .  .  .  .  .  .  .  Decl: *(obj @ 28)
    36  .  .  .  .  .  .  }
    37  .  .  .  .  .  }
    38  .  .  .  .  .  Type: *ast.StructType {
    39  .  .  .  .  .  .  Struct: 8:10
    40  .  .  .  .  .  .  Fields: *ast.FieldList {
    41  .  .  .  .  .  .  .  Opening: 8:17
    42  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {
    43  .  .  .  .  .  .  .  .  0: *ast.Field {
    44  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {
    45  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {
    46  .  .  .  .  .  .  .  .  .  .  .  NamePos: 9:2
    47  .  .  .  .  .  .  .  .  .  .  .  Name: "i"
    48  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {
    49  .  .  .  .  .  .  .  .  .  .  .  .  Kind: var
    50  .  .  .  .  .  .  .  .  .  .  .  .  Name: "i"
    51  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 43)
    52  .  .  .  .  .  .  .  .  .  .  .  }
    53  .  .  .  .  .  .  .  .  .  .  }
    54  .  .  .  .  .  .  .  .  .  }
    55  .  .  .  .  .  .  .  .  .  Type: *ast.Ident {
    56  .  .  .  .  .  .  .  .  .  .  NamePos: 9:4
    57  .  .  .  .  .  .  .  .  .  .  Name: "int"
    58  .  .  .  .  .  .  .  .  .  }
    59  .  .  .  .  .  .  .  .  }
    60  .  .  .  .  .  .  .  }
    61  .  .  .  .  .  .  .  Closing: 10:1
    62  .  .  .  .  .  .  }
    63  .  .  .  .  .  .  Incomplete: false
    64  .  .  .  .  .  }
    65  .  .  .  .  }
    66  .  .  .  }
    67  .  .  .  Rparen: -
    68  .  .  }
    69  .  .  2: *ast.GenDecl {
    70  .  .  .  TokPos: 13:1
    71  .  .  .  Tok: type
    72  .  .  .  Lparen: -
    73  .  .  .  Specs: []ast.Spec (len = 1) {
    74  .  .  .  .  0: *ast.TypeSpec {
    75  .  .  .  .  .  Name: *ast.Ident {
    76  .  .  .  .  .  .  NamePos: 13:6
    77  .  .  .  .  .  .  Name: "Bar"
    78  .  .  .  .  .  .  Obj: *ast.Object {
    79  .  .  .  .  .  .  .  Kind: type
    80  .  .  .  .  .  .  .  Name: "Bar"
    81  .  .  .  .  .  .  .  Decl: *(obj @ 74)
    82  .  .  .  .  .  .  }
    83  .  .  .  .  .  }
    84  .  .  .  .  .  Type: *ast.InterfaceType {
    85  .  .  .  .  .  .  Interface: 13:10
    86  .  .  .  .  .  .  Methods: *ast.FieldList {
    87  .  .  .  .  .  .  .  Opening: 13:20
    88  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {
    89  .  .  .  .  .  .  .  .  0: *ast.Field {
    90  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {
    91  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {
    92  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:2
    93  .  .  .  .  .  .  .  .  .  .  .  Name: "Do"
    94  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {
    95  .  .  .  .  .  .  .  .  .  .  .  .  Kind: func
    96  .  .  .  .  .  .  .  .  .  .  .  .  Name: "Do"
    97  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 89)
    98  .  .  .  .  .  .  .  .  .  .  .  }
    99  .  .  .  .  .  .  .  .  .  .  }
   100  .  .  .  .  .  .  .  .  .  }
   101  .  .  .  .  .  .  .  .  .  Type: *ast.FuncType {
   102  .  .  .  .  .  .  .  .  .  .  Func: -
   103  .  .  .  .  .  .  .  .  .  .  Params: *ast.FieldList {
   104  .  .  .  .  .  .  .  .  .  .  .  Opening: 14:4
   105  .  .  .  .  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {
   106  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Field {
   107  .  .  .  .  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {
   108  .  .  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {
   109  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:5
   110  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "ctx"
   111  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {
   112  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Kind: var
   113  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "ctx"
   114  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 106)
   115  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   116  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   117  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   118  .  .  .  .  .  .  .  .  .  .  .  .  .  Type: *ast.SelectorExpr {
   119  .  .  .  .  .  .  .  .  .  .  .  .  .  .  X: *ast.Ident {
   120  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:9
   121  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "context"
   122  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   123  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Sel: *ast.Ident {
   124  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:17
   125  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "Context"
   126  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   127  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   128  .  .  .  .  .  .  .  .  .  .  .  .  }
   129  .  .  .  .  .  .  .  .  .  .  .  }
   130  .  .  .  .  .  .  .  .  .  .  .  Closing: 14:24
   131  .  .  .  .  .  .  .  .  .  .  }
   132  .  .  .  .  .  .  .  .  .  .  Results: *ast.FieldList {
   133  .  .  .  .  .  .  .  .  .  .  .  Opening: -
   134  .  .  .  .  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {
   135  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Field {
   136  .  .  .  .  .  .  .  .  .  .  .  .  .  Type: *ast.Ident {
   137  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:26
   138  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "error"
   139  .  .  .  .  .  .  .  .  .  .  .  .  .  }
   140  .  .  .  .  .  .  .  .  .  .  .  .  }
   141  .  .  .  .  .  .  .  .  .  .  .  }
   142  .  .  .  .  .  .  .  .  .  .  .  Closing: -
   143  .  .  .  .  .  .  .  .  .  .  }
   144  .  .  .  .  .  .  .  .  .  }
   145  .  .  .  .  .  .  .  .  }
   146  .  .  .  .  .  .  .  }
   147  .  .  .  .  .  .  .  Closing: 15:1
   148  .  .  .  .  .  .  }
   149  .  .  .  .  .  .  Incomplete: false
   150  .  .  .  .  .  }
   151  .  .  .  .  }
   152  .  .  .  }
   153  .  .  .  Rparen: -
   154  .  .  }
   155  .  .  3: *ast.FuncDecl {
   156  .  .  .  Name: *ast.Ident {
   157  .  .  .  .  NamePos: 18:6
   158  .  .  .  .  Name: "main"
   159  .  .  .  .  Obj: *ast.Object {
   160  .  .  .  .  .  Kind: func
   161  .  .  .  .  .  Name: "main"
   162  .  .  .  .  .  Decl: *(obj @ 155)
   163  .  .  .  .  }
   164  .  .  .  }
   165  .  .  .  Type: *ast.FuncType {
   166  .  .  .  .  Func: 18:1
   167  .  .  .  .  Params: *ast.FieldList {
   168  .  .  .  .  .  Opening: 18:10
   169  .  .  .  .  .  Closing: 18:11
   170  .  .  .  .  }
   171  .  .  .  }
   172  .  .  .  Body: *ast.BlockStmt {
   173  .  .  .  .  Lbrace: 18:13
   174  .  .  .  .  List: []ast.Stmt (len = 1) {
   175  .  .  .  .  .  0: *ast.AssignStmt {
   176  .  .  .  .  .  .  Lhs: []ast.Expr (len = 1) {
   177  .  .  .  .  .  .  .  0: *ast.Ident {
   178  .  .  .  .  .  .  .  .  NamePos: 19:2
   179  .  .  .  .  .  .  .  .  Name: "a"
   180  .  .  .  .  .  .  .  .  Obj: *ast.Object {
   181  .  .  .  .  .  .  .  .  .  Kind: var
   182  .  .  .  .  .  .  .  .  .  Name: "a"
   183  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 175)
   184  .  .  .  .  .  .  .  .  }
   185  .  .  .  .  .  .  .  }
   186  .  .  .  .  .  .  }
   187  .  .  .  .  .  .  TokPos: 19:4
   188  .  .  .  .  .  .  Tok: :=
   189  .  .  .  .  .  .  Rhs: []ast.Expr (len = 1) {
   190  .  .  .  .  .  .  .  0: *ast.BasicLit {
   191  .  .  .  .  .  .  .  .  ValuePos: 19:7
   192  .  .  .  .  .  .  .  .  Kind: INT
   193  .  .  .  .  .  .  .  .  Value: "1"
   194  .  .  .  .  .  .  .  }
   195  .  .  .  .  .  .  }
   196  .  .  .  .  .  }
   197  .  .  .  .  }
   198  .  .  .  .  Rbrace: 20:1
   199  .  .  .  }
   200  .  .  }
   201  .  }
   202  .  Scope: *ast.Scope {
   203  .  .  Objects: map[string]*ast.Object (len = 3) {
   204  .  .  .  "Foo": *(obj @ 32)
   205  .  .  .  "Bar": *(obj @ 78)
   206  .  .  .  "main": *(obj @ 159)
   207  .  .  }
   208  .  }
   209  .  Imports: []*ast.ImportSpec (len = 1) {
   210  .  .  0: *(obj @ 12)
   211  .  }
   212  .  Unresolved: []*ast.Ident (len = 3) {
   213  .  .  0: *(obj @ 55)
   214  .  .  1: *(obj @ 119)
   215  .  .  2: *(obj @ 136)
   216  .  }
   217  }

4. AST树结构

// 该结构体位于标准包 go/ast/ast.go 中,有兴趣可以转跳到源码阅读更详尽的注释
type File struct {
	Doc        *CommentGroup   // 如果文件有文档,则文档会被存储在这个结构体中,否则为 nil
	Package    token.Pos       // "package"关键字,主要是所在的位置信息
	Name       *Ident          // package的名字
	Decls      []Decl          // 文件级别的声明。它包含文件中所有变量、函数、类型声明。如果文件中没有声明,则 decls 值为 nil
	Scope      *Scope          // 包级作用域。它代表包级作用域,包含所有在包内声明的变量和函数。它对当前文件有效
	Imports    []*ImportSpec   // imports in this file
	Unresolved []*Ident        // unresolved identifiers in this file。未使用的标识符
	Comments   []*CommentGroup // 文件中的所有注释。它包含文件中所有注释的列表
}

img

img

4.1. Doc

如果文件有文档,则文档会被存储在这个结构体中,否则为 nil

todo:目前没找到什么样的源代码解析成AST树后有Doc的

4.2. Package

*ast.File {
     1  .  Package: 1:1
     2  .  Name: *ast.Ident {
     3  .  .  NamePos: 1:9
     4  .  .  Name: "main"
     5  .  }

Package: 1:1, package关键字所在的位置

4.3. Name

img

type为ast.ident,表示它是一个变量值,可以看到内容为"main"

4.4. Decls

文件级别的声明。它包含文件中所有变量、函数、类型声明。如果文件中没有声明,则 decls 值为 nil

img

4.5. Decls总共有三种类型

img

4.5.1. BadDecl

语法出错的声明

4.5.2. GenDecl

常规的声明,包含以下部分

  • import
  • constant
  • type
  • variable
4.5.2.1. import

img

4.5.2.2. constant
4.5.2.3. type

img

4.5.2.4. variable

4.5.3. FunDecl

方法的声明

4.6. Scope

包级作用域。它代表包级作用域,包含所有在包内声明的变量和函数。它对当前文件有效

img

4.6.1. 示例如下

img

4.7. Imports

回顾以下File结构体定义,其中ImportsImportSpec类型数组

// 该结构体位于标准包 go/ast/ast.go 中,有兴趣可以转跳到源码阅读更详尽的注释
type File struct {
	Doc        *CommentGroup   // 如果文件有文档,则文档会被存储在这个结构体中,否则为 nil
	Package    token.Pos       // "package"关键字,主要是所在的位置信息
	Name       *Ident          // package的名字
	Decls      []Decl          // 文件级别的声明。它包含文件中所有变量、函数、类型声明。如果文件中没有声明,则 decls 值为 nil
	Scope      *Scope          // 包级作用域。它代表包级作用域,包含所有在包内声明的变量和函数。它对当前文件有效
	Imports    []*ImportSpec   // imports in this file
	Unresolved []*Ident        // unresolved identifiers in this file。未使用的标识符
	Comments   []*CommentGroup // 文件中的所有注释。它包含文件中所有注释的列表
}

ImportSpec结构体定义如下,一条import就是一个ImportSpec

// An ImportSpec node represents a single package import.
	ImportSpec struct {
		Doc     *CommentGroup // associated documentation; or nil
		Name    *Ident        // local package name (including "."); or nil
		Path    *BasicLit     // import path
		Comment *CommentGroup // line comments; or nil
		EndPos  token.Pos     // end of spec (overrides Path.Pos if nonzero)
	}

img

4.8. Unresolved

unresolved identifiers in this file。未使用的标识符

4.9. Comments

文件中的所有注释。它包含文件中所有注释的列表。实际上这块有问题,并没有注释解析出来

5. AST数节点类型

6. 参考资料

  1. Golang AST语法树使用教程及示例
  2. GoAst Viewer
  3. https://github.com/DrmagicE/ast-example
  4. [golang深入源代码系列之一:AST的遍历](

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1930099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第五十五天|101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

101.孤岛的总面积 题目链接:101.孤岛的总面积沉没孤岛 文档讲解:代码随想录 状态:不会 思路: 步骤1:将边界上的陆地变为海洋 步骤2:计算孤岛的总面积 题解: public class Main {// 保存四个方…

【UE5.1】NPC人工智能——02 NPC移动到指定位置

效果 步骤 1. 新建一个蓝图,父类选择“AI控制器” 这里命名为“BP_NPC_AIController”,表示专门用于控制NPC的AI控制器 2. 找到我们之前创建的所有NPC的父类“BP_NPC” 打开“BP_NPC”,在类默认值中,将“AI控制器类”一项设置为“…

动手学深度学习——3.多层感知机

1.线性模型 线性模型可能出错 例如,线性意味着单调假设: 任何特征的增大都会导致模型输出的增大(如果对应的权重为正), 或者导致模型输出的减小(如果对应的权重为负)。 有时这是有道理的。 例…

R绘制Venn图及其变换

我自己在用R做各种分析时有不少需要反复用到的基础功能,比如一些简单的统计呀,画一些简单的图等等,虽说具体实现的代码也不麻烦,但还是不太想每次用的时候去找之前的代码。 索性将常用的各种函数整成了一个包:pcutils…

前端JS特效第34集:jQuery俩张图片局部放大预览插件

jQuery俩张图片局部放大预览插件&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta http-equiv"X-UA-Co…

数据结构与算法02迭代|递归

目录 一、迭代(iteration) 1、for循环 2、while循环 二、递归&#xff08;recursion&#xff09; 1、普通递归 2、尾递归 3、递归树 三、对比 简介&#xff1a;在算法中&#xff0c;重复执行某个任务是常见的&#xff0c;它与复杂度息息相关&#xff0c;在程序中实现重…

MySQL MVCC原理

全称Multi-Version Concurrency Control&#xff0c;即多版本并发控制&#xff0c;主要是为了提高数据库的并发性能。 1、版本链 对于使用InnoDB存储引擎的表来说&#xff0c;它的聚簇索引记录中都包含两个必要的隐藏列&#xff1a; 1、trx_id&#xff1a;每次一个事务对某条…

connect by prior 递归查询

connect by prior 以公司组织架构举例&#xff0c;共四个层级&#xff0c;总公司&#xff0c;分公司&#xff0c;中心支公司&#xff0c;支公司 总公司level_code为1 下一层级的parent_id为上一层级的id&#xff0c;建立关联关系 SELECT id, name, LEVEL FROM org_info a STA…

区块链学习05-web3中solidity和move语言

Solidity 和 Move 语言的比较&#xff1a;Web3 开发中的两种选择 Solidity 和 Move 都是用于开发区块链平台智能合约的编程语言。它们具有一些相似之处&#xff0c;但也存在一些关键差异。 相似之处: Solidity 和 Move 都是图灵完备语言&#xff0c;这意味着它们可以表达计算…

提高引流精准性的策略

1、定位清晰&#xff1a;明确你的目标用户是谁&#xff0c;了解他们的需求和兴趣&#xff0c;定制内容和策略以吸引他们。 2、价值输出&#xff1a;提供有价值的内容或服务&#xff0c;让用户觉得添加你的微信是有益的&#xff0c;比如独家资讯、优惠券、专业咨询等。 3、筛选…

vs2019 QT无法打开源文件QModbusTcpClient

vs2019无法打开源文件QModbusTcpClient 如果配置的msvc2019,则查找到Include目录 然后包含&#xff1a; #include <QtSerialBus/qmodbustcpclient.h>

PostgreSQl 物化视图

物化视图&#xff08;Materialized View&#xff09;是 PostgreSQL 提供的一个扩展功能&#xff0c;它是介于视图和表之间的一种对象。 物化视图和视图的最大区别是它不仅存储定义中的查询语句&#xff0c;而且可以像表一样存储数据。物化视图和表的最大区别是它不支持 INSERT…

【设计模式】【创建型模式】【02工厂模式】

系列文章 可跳转到下面链接查看下表所有内容https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501文章浏览阅读2次。系列文章大全https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501 目录 系…

redis原理之底层数据结构(三)-quicklist

1.绪论 前面讲过的ziplist在查找元素的时候是o(n)的复杂度&#xff0c;如果ziplist长度太长&#xff0c;会导致查找元素很缓慢&#xff0c;而ziplist是拥有内存连续的优势&#xff0c;为了保留ziplist内存连续的优势&#xff0c;但是又不能保留太长的长度&#xff0c;我们出现…

MQ基础1

对应B站视频&#xff1a; MQ入门-01.MQ课程介绍_哔哩哔哩_bilibili 微服务一旦拆分&#xff0c;必然涉及到服务之间的相互调用&#xff0c;目前我们服务之间调用采用的都是基于OpenFeign的调用。这种调用中&#xff0c;调用者发起请求后需要等待服务提供者执行业务返回结果后…

【Linux杂货铺】期末总结篇3:用户账户管理命令 | 组账户管理命令

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux杂货铺、Linux实践室 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 第五章5.1 ⛳️Linux 账户5.2 ⛳️用户配置文件和目录&#xff08;未完待续&#xff09;5.2.1 …

java面向对象进阶篇--static

一、前言 java进阶篇已经开始了&#xff0c;先从面向对象开始&#xff0c;由于时间原因今天就只更新了static部分&#xff0c;内容上特别详细&#xff0c;一些特别的注意事项也在反复的提醒大家。 温馨提示一下&#xff0c;往后的java篇会越来越难&#xff0c;希望大家能够坚…

推荐5个实用的可视化工具

面对海量的数据&#xff0c;我们应该如何高效地提取其价值&#xff0c;让复杂的信息一目了然&#xff1f;这正是可视化工具大显身手的舞台。今天&#xff0c;我就来分享几款非常好用的数据可视化工具&#xff0c;它们不仅能够帮助你轻松驾驭数据&#xff0c;还能让你的工作汇报…

vite配置环境变量和使用,配置正确后import.meta.env.VITE_APP_BASE_URL编译报错的解决方法

一、配置&#xff1a; 1.新增四个环境文件 .env.development .env.test .env.production .env.pre 内容为不同环境的不同参数变量必须以VITE_APP开头&#xff0c;如&#xff1a; #接口地址 VITE_APP_BASE_URL"&#xffe5;&#xffe5;&#xffe5;&#xffe5;&#xff…

算法 —— 快速幂

目录 P1045 [NOIP2003 普及组] 麦森数 P1226 【模板】快速幂 原理I 原理II P1226 代码解析 P1045 代码解析 P1045 [NOIP2003 普及组] 麦森数 本题来自洛谷&#xff1a;P1045 [NOIP2003 普及组] 麦森数&#xff0c;根据题意&#xff0c;我们可以看到本题需要计算最少2的1…