golang AST語法樹解析

1. 源碼示例

package mainimport ("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 mainimport ("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:12  .  Name: *ast.Ident {3  .  .  NamePos: 1:94  .  .  Name: "main"5  .  }6  .  Decls: []ast.Decl (len = 4) {7  .  .  0: *ast.GenDecl {8  .  .  .  TokPos: 3:19  .  .  .  Tok: import10  .  .  .  Lparen: 3:811  .  .  .  Specs: []ast.Spec (len = 1) {12  .  .  .  .  0: *ast.ImportSpec {13  .  .  .  .  .  Path: *ast.BasicLit {14  .  .  .  .  .  .  ValuePos: 4:215  .  .  .  .  .  .  Kind: STRING16  .  .  .  .  .  .  Value: "\"context\""17  .  .  .  .  .  }18  .  .  .  .  .  EndPos: -19  .  .  .  .  }20  .  .  .  }21  .  .  .  Rparen: 5:122  .  .  }23  .  .  1: *ast.GenDecl {24  .  .  .  TokPos: 8:125  .  .  .  Tok: type26  .  .  .  Lparen: -27  .  .  .  Specs: []ast.Spec (len = 1) {28  .  .  .  .  0: *ast.TypeSpec {29  .  .  .  .  .  Name: *ast.Ident {30  .  .  .  .  .  .  NamePos: 8:631  .  .  .  .  .  .  Name: "Foo"32  .  .  .  .  .  .  Obj: *ast.Object {33  .  .  .  .  .  .  .  Kind: type34  .  .  .  .  .  .  .  Name: "Foo"35  .  .  .  .  .  .  .  Decl: *(obj @ 28)36  .  .  .  .  .  .  }37  .  .  .  .  .  }38  .  .  .  .  .  Type: *ast.StructType {39  .  .  .  .  .  .  Struct: 8:1040  .  .  .  .  .  .  Fields: *ast.FieldList {41  .  .  .  .  .  .  .  Opening: 8:1742  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {43  .  .  .  .  .  .  .  .  0: *ast.Field {44  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {45  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {46  .  .  .  .  .  .  .  .  .  .  .  NamePos: 9:247  .  .  .  .  .  .  .  .  .  .  .  Name: "i"48  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {49  .  .  .  .  .  .  .  .  .  .  .  .  Kind: var50  .  .  .  .  .  .  .  .  .  .  .  .  Name: "i"51  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 43)52  .  .  .  .  .  .  .  .  .  .  .  }53  .  .  .  .  .  .  .  .  .  .  }54  .  .  .  .  .  .  .  .  .  }55  .  .  .  .  .  .  .  .  .  Type: *ast.Ident {56  .  .  .  .  .  .  .  .  .  .  NamePos: 9:457  .  .  .  .  .  .  .  .  .  .  Name: "int"58  .  .  .  .  .  .  .  .  .  }59  .  .  .  .  .  .  .  .  }60  .  .  .  .  .  .  .  }61  .  .  .  .  .  .  .  Closing: 10:162  .  .  .  .  .  .  }63  .  .  .  .  .  .  Incomplete: false64  .  .  .  .  .  }65  .  .  .  .  }66  .  .  .  }67  .  .  .  Rparen: -68  .  .  }69  .  .  2: *ast.GenDecl {70  .  .  .  TokPos: 13:171  .  .  .  Tok: type72  .  .  .  Lparen: -73  .  .  .  Specs: []ast.Spec (len = 1) {74  .  .  .  .  0: *ast.TypeSpec {75  .  .  .  .  .  Name: *ast.Ident {76  .  .  .  .  .  .  NamePos: 13:677  .  .  .  .  .  .  Name: "Bar"78  .  .  .  .  .  .  Obj: *ast.Object {79  .  .  .  .  .  .  .  Kind: type80  .  .  .  .  .  .  .  Name: "Bar"81  .  .  .  .  .  .  .  Decl: *(obj @ 74)82  .  .  .  .  .  .  }83  .  .  .  .  .  }84  .  .  .  .  .  Type: *ast.InterfaceType {85  .  .  .  .  .  .  Interface: 13:1086  .  .  .  .  .  .  Methods: *ast.FieldList {87  .  .  .  .  .  .  .  Opening: 13:2088  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {89  .  .  .  .  .  .  .  .  0: *ast.Field {90  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {91  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {92  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:293  .  .  .  .  .  .  .  .  .  .  .  Name: "Do"94  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {95  .  .  .  .  .  .  .  .  .  .  .  .  Kind: func96  .  .  .  .  .  .  .  .  .  .  .  .  Name: "Do"97  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 89)98  .  .  .  .  .  .  .  .  .  .  .  }99  .  .  .  .  .  .  .  .  .  .  }100  .  .  .  .  .  .  .  .  .  }101  .  .  .  .  .  .  .  .  .  Type: *ast.FuncType {102  .  .  .  .  .  .  .  .  .  .  Func: -103  .  .  .  .  .  .  .  .  .  .  Params: *ast.FieldList {104  .  .  .  .  .  .  .  .  .  .  .  Opening: 14:4105  .  .  .  .  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {106  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Field {107  .  .  .  .  .  .  .  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {108  .  .  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Ident {109  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:5110  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "ctx"111  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Obj: *ast.Object {112  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Kind: var113  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "ctx"114  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 106)115  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }116  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }117  .  .  .  .  .  .  .  .  .  .  .  .  .  }118  .  .  .  .  .  .  .  .  .  .  .  .  .  Type: *ast.SelectorExpr {119  .  .  .  .  .  .  .  .  .  .  .  .  .  .  X: *ast.Ident {120  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:9121  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "context"122  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }123  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Sel: *ast.Ident {124  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:17125  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "Context"126  .  .  .  .  .  .  .  .  .  .  .  .  .  .  }127  .  .  .  .  .  .  .  .  .  .  .  .  .  }128  .  .  .  .  .  .  .  .  .  .  .  .  }129  .  .  .  .  .  .  .  .  .  .  .  }130  .  .  .  .  .  .  .  .  .  .  .  Closing: 14:24131  .  .  .  .  .  .  .  .  .  .  }132  .  .  .  .  .  .  .  .  .  .  Results: *ast.FieldList {133  .  .  .  .  .  .  .  .  .  .  .  Opening: -134  .  .  .  .  .  .  .  .  .  .  .  List: []*ast.Field (len = 1) {135  .  .  .  .  .  .  .  .  .  .  .  .  0: *ast.Field {136  .  .  .  .  .  .  .  .  .  .  .  .  .  Type: *ast.Ident {137  .  .  .  .  .  .  .  .  .  .  .  .  .  .  NamePos: 14:26138  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Name: "error"139  .  .  .  .  .  .  .  .  .  .  .  .  .  }140  .  .  .  .  .  .  .  .  .  .  .  .  }141  .  .  .  .  .  .  .  .  .  .  .  }142  .  .  .  .  .  .  .  .  .  .  .  Closing: -143  .  .  .  .  .  .  .  .  .  .  }144  .  .  .  .  .  .  .  .  .  }145  .  .  .  .  .  .  .  .  }146  .  .  .  .  .  .  .  }147  .  .  .  .  .  .  .  Closing: 15:1148  .  .  .  .  .  .  }149  .  .  .  .  .  .  Incomplete: false150  .  .  .  .  .  }151  .  .  .  .  }152  .  .  .  }153  .  .  .  Rparen: -154  .  .  }155  .  .  3: *ast.FuncDecl {156  .  .  .  Name: *ast.Ident {157  .  .  .  .  NamePos: 18:6158  .  .  .  .  Name: "main"159  .  .  .  .  Obj: *ast.Object {160  .  .  .  .  .  Kind: func161  .  .  .  .  .  Name: "main"162  .  .  .  .  .  Decl: *(obj @ 155)163  .  .  .  .  }164  .  .  .  }165  .  .  .  Type: *ast.FuncType {166  .  .  .  .  Func: 18:1167  .  .  .  .  Params: *ast.FieldList {168  .  .  .  .  .  Opening: 18:10169  .  .  .  .  .  Closing: 18:11170  .  .  .  .  }171  .  .  .  }172  .  .  .  Body: *ast.BlockStmt {173  .  .  .  .  Lbrace: 18:13174  .  .  .  .  List: []ast.Stmt (len = 1) {175  .  .  .  .  .  0: *ast.AssignStmt {176  .  .  .  .  .  .  Lhs: []ast.Expr (len = 1) {177  .  .  .  .  .  .  .  0: *ast.Ident {178  .  .  .  .  .  .  .  .  NamePos: 19:2179  .  .  .  .  .  .  .  .  Name: "a"180  .  .  .  .  .  .  .  .  Obj: *ast.Object {181  .  .  .  .  .  .  .  .  .  Kind: var182  .  .  .  .  .  .  .  .  .  Name: "a"183  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 175)184  .  .  .  .  .  .  .  .  }185  .  .  .  .  .  .  .  }186  .  .  .  .  .  .  }187  .  .  .  .  .  .  TokPos: 19:4188  .  .  .  .  .  .  Tok: :=189  .  .  .  .  .  .  Rhs: []ast.Expr (len = 1) {190  .  .  .  .  .  .  .  0: *ast.BasicLit {191  .  .  .  .  .  .  .  .  ValuePos: 19:7192  .  .  .  .  .  .  .  .  Kind: INT193  .  .  .  .  .  .  .  .  Value: "1"194  .  .  .  .  .  .  .  }195  .  .  .  .  .  .  }196  .  .  .  .  .  }197  .  .  .  .  }198  .  .  .  .  Rbrace: 20:1199  .  .  .  }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   // 如果文件有文檔,則文檔會被存儲在這個結構體中,否則為 nilPackage    token.Pos       // "package"關鍵字,主要是所在的位置信息Name       *Ident          // package的名字Decls      []Decl          // 文件級別的聲明。它包含文件中所有變量、函數、類型聲明。如果文件中沒有聲明,則 decls 值為 nilScope      *Scope          // 包級作用域。它代表包級作用域,包含所有在包內聲明的變量和函數。它對當前文件有效Imports    []*ImportSpec   // imports in this fileUnresolved []*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:12  .  Name: *ast.Ident {3  .  .  NamePos: 1:94  .  .  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   // 如果文件有文檔,則文檔會被存儲在這個結構體中,否則為 nilPackage    token.Pos       // "package"關鍵字,主要是所在的位置信息Name       *Ident          // package的名字Decls      []Decl          // 文件級別的聲明。它包含文件中所有變量、函數、類型聲明。如果文件中沒有聲明,則 decls 值為 nilScope      *Scope          // 包級作用域。它代表包級作用域,包含所有在包內聲明的變量和函數。它對當前文件有效Imports    []*ImportSpec   // imports in this fileUnresolved []*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 nilName    *Ident        // local package name (including "."); or nilPath    *BasicLit     // import pathComment *CommentGroup // line comments; or nilEndPos  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.pswp.cn/web/45772.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45772.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45772.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[雜談] 關于 Mac 電腦使用 Logitech 鼠標導致 Vscode 側鍵無法進行代碼前進、回退的問題

我個人使用的是一臺 14 寸的 Mac_Apple_M1,外接鍵盤顯示器羅技的 MX Master 3 for Mac 的鼠標。 之前一直使用的 GoLand 開發,查看代碼時進行代碼跳轉就很方便,滾輪鍵 進入函數方法,鼠標側鍵進行前進、后退。看代碼完全可以右手單…

【大模型入門】LLM-AI大模型介紹

大語言模型 (LLM) 背景 🍹大語言模型 (Large Language Model) 是一種人工智能模型, 它們通常包含數千億甚至更多的參數,并在大規模數據集上進行訓練。大語言模型可以處理多種自然語言任務,如文本分類、問答、翻譯、對話等等。 自然語言模型…

qt explicit 啥意思

explicit 在 Qt 和 C 中是一個關鍵字,主要用于修飾類的構造函數。其含義和用法可以歸納為以下幾點: 意義: explicit 英文直譯為“明確的”、“顯式的”。在 C 中,當一個構造函數只接受一個參數時,它可能會被編譯器用于…

【Nail it】ROS1 ROS2 通信(ros2/ros1_bridge)

情況說明:目標是實現ros2容器和ros1主機的通信,可以起一個ros1容器作為橋梁(若是在一個主機同時包含ros1&ros2,配置更加方便). 1.起一個 noetic 的容器 docker run -it --network host --name my_bridge ros:noe…

Java中的成員內部類

Java中的成員內部類(也稱為非靜態內部類)是定義在另一個類(外部類)內部的類。 這種內部類與它的外部類之間有著緊密的聯系,主要體現在幾個方面:它可以訪問外部類的所有成員(包括私有成員&#…

C++小白Python選手2小時入門C++

學習鏈接:C入門/2小時從C到C快速入門(2018,C教程) C在C語言的基礎上增加了面向對象和通用算法語言特征。 C頭文件不必是.h結尾,C頭文件舉例:cmath、cstdio注釋:單行//、多行/**/為了防止名字沖…

MQ基礎1

對應B站視頻: MQ入門-01.MQ課程介紹_嗶哩嗶哩_bilibili 微服務一旦拆分,必然涉及到服務之間的相互調用,目前我們服務之間調用采用的都是基于OpenFeign的調用。這種調用中,調用者發起請求后需要等待服務提供者執行業務返回結果后…

【JavaScript腳本宇宙】強大的自然語言處理:六款JavaScript庫詳解

從語義到實體:深入了解JavaScript自然語言處理庫 前言 隨著人工智能和自然語言處理技術的飛速發展,JavaScript在這一領域也有了越來越多的應用。本文將介紹幾個優秀的JavaScript庫,它們專注于處理英語文本,并提供了豐富的功能和…

求立方體面積體積以及判斷(c++)

代碼&#xff1a; #include<iostream> using namespace std;class Cube { public:void setL(int l){m_L l;}int getL(){return m_L;}void setW(int w){m_W w;}int getW(){return m_W;}void setH(int h){m_H h;}int getH(){return m_H;}int calculateS(){return 2 * (…

netdata 監控軟件安裝與學習

netdata官網 netdata操作文檔 前言&#xff1a; netdata是一款監控軟件&#xff0c;可以監控多臺主機也可以監控單臺主機&#xff0c;監控單臺主機時&#xff0c;開箱即用&#xff0c;web ui很棒。 環境&#xff1a; [root192 ~]# cat /etc/system-release CentOS Linux rel…

徹底清理Conda環境:使用conda remove命令的終極指南

徹底清理Conda環境&#xff1a;使用conda remove命令的終極指南 在Conda環境中&#xff0c;隨著時間的推移&#xff0c;可能會積累大量不再需要的包和它們的依賴項。這不僅會占用寶貴的磁盤空間&#xff0c;還可能影響環境的性能。conda remove命令是Conda提供的一個強大工具&…

GD32F407VET6新建固件庫工程并下載運行

零、所需文件及環境&#xff1a; 1、固件庫的壓縮包 GD32F4xx_Firmware_Library_V3.2.0.7z 官網 2、GD32F407的keil支持包 官網 兆易創新GigaDevice-資料下載兆易創新GD32 MCU 2、 keilkilll.bat 用來刪除編譯過程文件 可以不要 &#xff08;原子、野火資料里都有&…

LeetCode熱題100(JavaScript)

哈希 兩數之和 暴力解法 /*** param {number[]} nums* param {number} target* return {number[]}*/ var twoSum function(nums, target) {for(let i 0;i<nums.length;i){let x1 nums[i]for(let j 0 ; j<nums.length;j){if(i!j){let x2 nums[j]if(x1x2target){ret…

算法金 | 來了,pandas 2.0

大俠幸會&#xff0c;在下全網同名「算法金」 0 基礎轉 AI 上岸&#xff0c;多個算法賽 Top 「日更萬日&#xff0c;讓更多人享受智能樂趣」 今日 210/10000 Pandas 是一個強大的數據分析庫&#xff0c;廣泛應用于科學研究、金融分析、商業智能等領域。它提供了高效的數據結構…

[WUSTCTF2020]level4題解 入土為安的第三天

二叉樹 Practice my Data Structure code..... Typing....Struct.....char....*left....*right............emmmmm...OK! Traversal! Traversal type 1:2f0t02T{hcsiI_SwA__r7Ee} Traversal type 2:20f0Th{2tsIS_icArE}e7__w Traversal type 3: //type3(&x[22]); No w…

samba服務、安裝-smbpasswd工具、pdbedit工具、testparm工具

在Windows構建的網絡生態里&#xff0c;各主機間的文件及打印資源共享&#xff0c;主要依賴微軟專有的SMB/CIFS網絡協議來達成。SMB&#xff08;即Server Message Block&#xff0c;服務消息塊&#xff09;與CIFS&#xff08;全稱Common Internet File System&#xff0c;通用互…

ShardingSphere的項目應用

1. 事情的起因 最近,隨著業務的發展,我們的項目面臨著日益增長的數據挑戰。系統使用的數據庫是mysql,每天的增量差不多在百萬左右,由于沒有進行分庫分表,以前設置的單表保存已經越發不能滿足需求,所以想維持表的性能,甲方考慮對這些大數據量的表進行分表操作,同時也采…

MySQL left join、right join以及inner join的區別 ?

LEFT JOIN&#xff08;左連接&#xff09;、RIGHT JOIN&#xff08;右連接&#xff09;和INNER JOIN&#xff08;內連接&#xff09;是SQL中用于連接兩個或多個表以檢索數據的重要操作。它們之間的主要區別在于如何處理那些在連接條件下沒有匹配的行。下面通過具體的例子來說明…

掃地機器人如何解決安全性與隱私保護

掃地機器人在解決安全性與隱私保護方面&#xff0c;需要從多個角度入手&#xff0c;包括產品設計、技術實現、用戶教育以及法律法規遵守等方面。以下是具體的解決方案&#xff1a; 一、安全性解決方案 1.提升避障能力&#xff1a;使用先進的傳感器技術&#xff0c;如激光雷達、…

JavaScript switch 語句

JavaScript switch 語句 JavaScript 中的 switch 語句是一種多分支選擇結構&#xff0c;用于根據變量的值執行不同的代碼塊。它提供了一種簡潔的方式來替代多個 if...else 語句&#xff0c;特別是在處理多個條件時。 基本語法 switch (expression) {case value1:// 代碼塊 1…