Go 语言基础知识语法
很早听人说过一句话:“每年学习(接触)一门新的编程语言”,这听起来可能有点不太现实,但是其实很多种语言都是相通的。掌握新的编程语言不仅仅是增加职业工具箱中的工具,更是一种扩展我们思维方式、解决问题能力和创新能力的方式。每种语言都有其独特的构造和哲学,从中我们可以获得新的见解,这些见解可以转化为处理日常任务时的新技能和更广阔的视角。
1 Go 语言背景
Go 语言被称为 21 世纪的 C 语言,最终的目标据说是设计网络和多核时代的 C 语言。
Go 语言的历史可以说是充满了奇闻和趣事,故事要从 2007 年说起,当时谷歌的工程师们因为软件开发过程中频繁使用的 C++存在一些痛点,比如编译速度慢、语言复杂等。于是,由 Robert Griesemer、Rob Pike 和 Ken Thompson 三位谷歌工程师联合发起了一个新的项目,旨在开发一门更高效、更简洁的编程语言。
他们的努力在 2009 年开始见到成果,那一年的 3 月,Go 语言正式面向全球开源,并发布了首个公开的版本。
Go 语言的设计目标是提供一种简洁、高效和易于使用的编程语言,以满足现代软件开发的需求。它借鉴了其他语言的优点,同时也摒弃了一些复杂性和冗余性。Go 语言拥有强大的并发性能和内置的垃圾回收机制,使其成为构建高性能和可伸缩的应用程序的理想选择。
有趣的是,Go 语言的名称源自游戏世界。根据创始人之一 Rob Pike 的说法,他们希望给这门语言一个简短而有力的名称,于是取名为"Go",寓意着前进、快速和简洁。
2 为什么要学习 Go 语言
学习 Go 语言(也被称为 Golang)有多种原因,它是一门现代的、高效的编程语言,适用于各种应用场景。以下是学习 Go 语言的一些主要原因:
- 高效性能: Go语言被设计成具有高效的执行性能。它的编译速度快,运行时性能优秀,适用于需要快速响应时间的应用程序,如网络服务和分布式系统。
- 并发支持: Go语言内置了强大的并发支持,通过goroutines和channels可以轻松实现并发编程,这对于构建高性能、高并发的应用程序非常有用。
- 内置工具: Go语言提供了丰富的标准库,包括网络、文本处理、加密、测试等方面的工具,使开发变得更加便捷。
- 静态类型检查: Go是一门静态类型语言,它在编译时进行类型检查,有助于减少运行时错误,提高代码的稳定性和可维护性。
- 跨平台支持: Go语言支持多个操作系统和体系结构,可以编写跨平台的应用程序。
- 开源社区: Go语言拥有活跃的开源社区,提供了大量的第三方库和工具,使开发人员能够更轻松地构建各种应用。
- 学习曲线低: Go语言的语法相对简单,与其他编程语言相比,学习曲线较低,新手可以相对快速地上手。
- Google支持: Go语言是由Google开发的,Google在许多项目中使用Go语言,这表明它在大规模系统开发方面有强大的支持。
- 云原生和微服务: Go语言在云原生和微服务架构中得到广泛应用,如Docker和Kubernetes等重要工具都是用Go语言编写的。
3 快速开始 Hello World
下面是在 Mac 上的实现:
3.1 安装 Go 环境
- 访问官方Go下载页面 https://go.dev/dl/ ,选择适合你操作系统的安装包,并下载最新版本的 Go 安装程序。
- 执行下载的安装程序,并按照提示进行安装。默认情况下,Go会安装到一个默认的目录,不需要进行额外配置。
- 验证 Go 是否安装成功,打开终端或命令行窗口,运行以下命令:
go version
如果显示 Go 的版本号,说明 Go 已成功安装。

3.2 编写第一个 go 程序
-
打开你喜欢的文本编辑器,创建一个新文件,将以下代码复制并粘贴到文件中:
package mainimport "fmt"func main() {fmt.Println("Hello, World!") }这是一个简单的 Go 程序,它会输出"Hello, World!"。
-
保存文件,通常使用
.go扩展名,比如hello.go。
在上面的代码中,我们定义了一个包,例如 main
package main
我们引入了一个标准的包:
import "fmt"
最后是我们最重要的 main 函数,它是应用程序的入口,就像 C、Java 或 C# 等其他语言一样。
func main() {...}
3.3 运行 Go 程序
-
打开终端或命令行窗口,导航到包含你的 Go 程序文件的目录。
-
使用以下命令来编译和运行程序:
go run hello.go如果一切正常,你将在终端上看到输出结果:“Hello, World!”。

这就是编写并运行第一个 Go 程序的基本步骤。你现在已经安装了 Go 环境,可以开始编写更多的 Go 代码并探索 Go 语言的功能和库。请注意,Go 具有强制的代码格式要求,你可以使用 gofmt 工具来格式化你的 Go 代码以符合标准。
Go 语言是编译型的语言,Go 的工具链将程序的源文件转变成为机器相关的二进制指令,这些工具可以通过单一的 go 命令配合其子命令进行使用,最简单的命令就是 run,它将一个或多个 .go 为后缀的源文件进行编译,链接,最后生成可执行文件。
如果我们不是一次性的实验,我们可以先编译输出一个可复用的程序,可以通过 build 来实现:
go build hello.go
上面的命令会生成一个 hello 的二进制程序,可以不经过任何的处理,随时可以运行:
./hello

4 Go 语言编程基本认识
4.1 包
Go 的标准库中有 100 多个包用来完成输入,输出,排序,文本处理等任务,比如我们常用的 fmt 包中的函数大多数是用于格式化的输入输出的。
main 包比较特殊,用于定义一个独立的可执行程序,而不是库。同样的,main 包中的 main 函数也是特殊的存在,main 函数相当于程序的入口,总是在程序开始执行的地方。
我们如果需要使用某一个包的内容,需要精准地导入该包,比如:
import("fmt""os"
)
4.2 函数
一个函数的声明由 func 关键字,函数名,参数列表(main 函数的参数是空的),返回值列表(可以为空),放在大括号内的函数体组成,函数体定义函数时用来做什么的。
Go 语言不需要再语句或者声明后面加上分号,除非是多个语句或者声明出现在同一行。Go 语言对于代码的格式化要求非常的严格,比如函数定义的 “{” 必须和关键字 “func” 在同一行,不能独自作为一行。
4.3 循环
Go 语言中有两种主要的循环结构:for 循环和 range 循环。下面我会分别介绍这两种循环的用法。
for 循环在 Go 语言中可以用来执行一段代码块多次,通常有三种基本形式:
4.3.1 基本的 for 循环:
for 初始化语句; 条件表达式; 后续语句 {// 循环体
}
示例:
for i := 0; i < 5; i++ {fmt.Println(i)
}
4.3.1.1 省略初始化语句的 for 循环:
for ; 条件表达式; 后续语句 {// 循环体
}
示例:
j := 0
for ; j < 5; j++ {fmt.Println(j)
}
4.3.1.2 省略初始化语句和后续语句的 for 循环:
for ; 条件表达式; {// 循环体
}
示例:
k := 0
for k < 5 {fmt.Println(k)k++
}
4.3.1.3 无限循环:
for {// 无限循环体
}
示例:
for {fmt.Println("无限循环")
}
4.3.2 range 循环
range 循环用于迭代数组、切片、映射(map)、字符串等数据结构的元素。它的基本语法如下:
for index, value := range 集合 {// 循环体
}
示例:
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {fmt.Printf("索引:%d,值:%d\n", index, value)
}
上述示例中,range 循环会依次将切片 numbers 中的元素的索引和值赋值给 index 和 value 变量,并执行循环体。
这就是 Go 语言中两种常见的循环方式,我们可以根据具体的需求选择合适的循环结构。
4.4 声明
Go 语言支持多种声明方式,用于声明变量、常量、类型等。以下是 Go 语言中常见的声明方式:
-
变量声明:
var variableName dataType // 声明一个变量示例:
var age int // 声明一个整数变量或者使用简短声明方式:
variableName := value // 使用简短声明方式初始化并声明一个变量示例:
name := "Alice" // 声明一个字符串变量并初始化为 "Alice" -
常量声明:
const constantName dataType = value // 声明一个常量示例:
const pi = 3.1415926 // 声明一个浮点数常量 -
类型声明:
type typeName typeLiteral // 声明一个自定义类型示例:
type Celsius float64 // 声明一个自定义的摄氏度类型 -
多个变量或常量同时声明:
var (variable1 dataType1 = value1variable2 dataType2 = value2// ... )示例:
var (name = "Bob"age = 30email = "bob@example.com" ) -
短声明方式声明多个变量:
var (variable1, variable2, variable3 = value1, value2, value3 )示例:
var (x, y, z = 1, 2, 3 ) -
声明并初始化映射(map)、切片(slice)、通道(channel)等复合类型:
mapVariable := make(map[keyType]valueType) sliceVariable := make([]dataType, length, capacity) channelVariable := make(chan dataType)示例:
scores := make(map[string]int) names := make([]string, 0, 10) dataChannel := make(chan int)
这些是 Go 语言中常见的声明方式,我们可以根据需要选择适合的方式来声明变量、常量和自定义类型。
4.5 类型
Go 语言具有多种基本数据类型和复合数据类型。以下是 Go 语言中常见的数据类型:
4.5.1 基本数据类型
-
整数类型(Integer Types):
int:有符号整数类型,根据计算机架构可以是 32 位或 64 位。int8、int16、int32、int64:有符号整数类型,分别占 8、16、32、64 位。uint:无符号整数类型,根据计算机架构可以是 32 位或 64 位。uint8、uint16、uint32、uint64:无符号整数类型,分别占 8、16、32、64 位。
-
浮点数类型(Floating-Point Types):
float32:单精度浮点数类型。float64:双精度浮点数类型。
-
复数类型(Complex Types):
complex64:包含 32 位实部和 32 位虚部的复数类型。complex128:包含 64 位实部和 64 位虚部的复数类型。
-
布尔类型(Boolean Type):
bool:表示布尔值,只有两个可能的值:true和false。
-
字符串类型(String Type):
string:表示文本字符串。
-
字符类型(Character Type):
byte:uint8的别名,通常用于表示 ASCII 字符。rune:int32的别名,通常用于表示 Unicode 字符。
4.5.2 复合数据类型
-
数组类型(Array Types):
array:具有固定长度的数组,元素类型相同。
-
切片类型(Slice Types):
slice:可变长度的切片,基于数组创建。
-
映射类型(Map Types):
map:键值对集合,用于实现关联数组。
-
结构体类型(Struct Types):
struct:用户自定义的复合数据类型,可以包含不同类型的字段。
-
通道类型(Channel Types):
chan:用于在 Go 协程之间传递数据的通信机制。
-
函数类型(Function Types):
func:函数类型,可以作为参数传递给其他函数。
-
接口类型(Interface Types):
interface:一组方法的抽象集合,用于定义对象的行为。
-
指针类型(Pointer Types):
pointer:指向某个变量内存地址的指针类型。
这些是 Go 语言中的常见数据类型。每种类型都有其用途和特点,你可以根据需求选择合适的类型来定义变量和数据结构。
4.6 并发
Go 语言(也称为 Golang)是一种支持并发编程的编程语言,它内置了许多特性和工具,使并发编程更加容易和高效。Go 语言的并发模型基于 Goroutines 和 Channels。
以下是一些关于 Go 语言并发编程的基本概念和技术:
-
Goroutines(协程):Goroutine 是 Go 语言中的轻量级线程,由 Go 语言的运行时系统管理。与传统的线程相比,Goroutines 的创建和销毁成本非常低,因此可以轻松创建成千上万个 Goroutines。你可以使用
go关键字来创建一个新的 Goroutine。go someFunction() // 创建一个新的Goroutine来执行someFunction -
Channels(通道):通道是 Goroutines 之间用于通信的安全机制。它们可以用来传递数据或信号。通道有两种类型:带缓冲的通道和非缓冲通道。通道可以用于同步和协调 Goroutines 之间的操作。
ch := make(chan int) // 创建一个整数类型的非缓冲通道 ch <- 42 // 向通道发送数据 value := <-ch // 从通道接收数据 -
并发控制:Go 语言提供了一些工具,如
sync包中的WaitGroup和Mutex,用于控制并发程序的执行流程和共享资源的访问。WaitGroup用于等待一组 Goroutines 完成,而Mutex用于实现互斥锁,以确保共享数据的安全访问。var wg sync.WaitGroup var mu sync.Mutex -
Select 语句:
select语句用于处理多个通道操作,允许你选择首先准备好的通道来执行操作,从而避免 Goroutines 在等待某个通道操作时被阻塞。select {case result := <-ch1:// 处理ch1的数据case result := <-ch2:// 处理ch2的数据 } -
并发模式:Go 语言支持多种并发模式,包括生产者-消费者、工作池、并行迭代等。你可以根据具体的应用场景选择合适的模式。
下面是一个简单的 Go 语言并发编程示例,演示了如何使用 Goroutines 和 Channels 来实现并发执行:
package mainimport ("fmt""time"
)func main() {ch := make(chan int)// 启动两个Goroutinesgo produce(ch)go consume(ch)// 等待一段时间,以便Goroutines完成time.Sleep(10 * time.Second)
}func produce(ch chan int) {for i := 0; i < 5; i++ {ch <- itime.Sleep(1 * time.Second)}close(ch)
}func consume(ch chan int) {for val := range ch {fmt.Println("Received:", val)}
}
这个示例中,一个 Goroutine 用于生成数据,另一个 Goroutine 用于消费数据,它们通过通道进行通信。这种模式可以应用于各种并发编程场景,如并行处理任务、数据流处理等,结果如下:

4.7 简单 web 编程
使用 Go 语言编写简单的 Web 应用程序通常涉及使用 Go 的标准库中的 net/http 包。以下是一个创建简单 Web 服务器的示例:
package mainimport ("fmt""net/http"
)func helloHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello, World!")
}func main() {http.HandleFunc("/hello", helloHandler)// 启动Web服务器,监听端口8080if err := http.ListenAndServe(":8080", nil); err != nil {panic(err)}
}
在上面的示例中,我们首先导入 net/http 包,然后定义了一个 helloHandler 函数,该函数会在用户访问 /hello 路径时执行。http.HandleFunc 函数用于将 helloHandler 与指定的 URL 路径关联起来。
最后,我们使用 http.ListenAndServe 函数启动一个 Web 服务器,监听端口 8080。当你访问 http://localhost:8080/hello 时,服务器会响应并显示 “Hello, World!”。

这只是一个简单的示例,Go 的 net/http 包提供了更多的功能,允许你构建更复杂的 Web 应用程序,包括路由、中间件、模板渲染等。你还可以考虑使用外部的 Web 框架,如 Gin 或 Echo,来简化 Web 应用程序的开发。
5 小结
当你决定学习 Go 语言时,你正在迈出一步通向编程世界的精彩旅程。Go 是一门强大而富有表现力的编程语言,它具备一系列独特的特性,让你能够构建高效、可维护、并发安全的应用程序。
编程是一项持之以恒的工作,就像是长途跋涉。它不一定总是轻松的,但在你坚持不懈的过程中,你将逐渐见证自己的成长。每一行代码都是你通向成功的一步,即使它们是缓慢而小小的一步。
作者: 秦怀,个人站点 秦怀杂货店,纵使缓慢,驰而不息。
相关文章:
Go 语言基础知识语法
很早听人说过一句话:“每年学习(接触)一门新的编程语言”,这听起来可能有点不太现实,但是其实很多种语言都是相通的。掌握新的编程语言不仅仅是增加职业工具箱中的工具,更是一种扩展我们思维方式、解决问题…...
贪心算法part05
文章参考来源代码随想录 (programmercarl.com) 56. 合并区间 本题和前几题类似,都是判断上一个元素的右边界与当前元素的左边界大小关系 但是需要注意是:本题需要更新结果数组元素的右边界,因此比较的是数组最后一个元素右边界与当前元素左…...
02、SpringMVC核心(上)
一、RequestMapping注解 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping @Reflective({ControllerMappingReflectiveProcessor.class}) public @interface RequestMapping {String name() default "";…...
EasyPlayerPro的同一个组件实例根据url不同展示视频流
效果 学习 url的组成 webrtc://192.168.1.225:8101/index/api/webrtc?applive&stream001&typeplay 协议部分 webrtc://: 这表示使用 WebRTC 协议来进行实时通信。WebRTC 允许浏览器之间直接交换音频、视频和其他数据,而不需要通过中间服务器 主机和端口部分…...
哈希表介绍、实现与封装
哈希表介绍、实现与封装 一、哈希概念二、哈希表实现直接定址法其他映射方法介绍1. 哈希冲突2. 负载因子3. 将关键字转为整数4. 设计哈希函数除法散列法 / 除留余数法乘法散列法全域散列法其他方法 将关键字转为整数处理哈希冲突开放定址法线性探测二次探测双重散列 开放定址法…...
使用vm配置网络
查看本地ip 配置vm网络 配置固定ip vi /etc/sysconfig/network-script/ifcfg-ens33参考 vm使用nat模式,导致vm中docker部署的服务,无法通过局域网中其他机器连接 https://www.cnblogs.com/junwind/p/14345385.html 三张图看懂vm中,三种网…...
OpenStack介绍
OpenStack概述 OpenStack是一个开源的云计算管理平台软件,主要用于构建和管理云计算环境。它允许企业或组织通过数据中心的物理服务器创建和管理虚拟机、存储资源和网络等云计算服务。其核心组件包括计算(Nova)、网络(Neutron)、存储(Cinder、Swift)等。这些组件相互协作…...
力扣93题:复原 IP 地址
力扣93题:复原 IP 地址(C语言实现详解) 题目描述 给定一个只包含数字的字符串 s,复原它并返回所有可能的 IP 地址格式。 有效的 IP 地址需满足以下条件: IP 地址由四个整数(每个整数位于 0 到 255 之间…...
mock.js介绍
mock.js http://mockjs.com/ 1、mock的介绍 *** 生成随机数据,拦截 Ajax 请求。** 通过随机数据,模拟各种场景;不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据;支持生成随机的文本、数字…...
React开发 - 技术细节汇总一
React简介 React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。 ui render (data) -> 单向数据流 MVC // model var myapp {}; // …...
【论文复现】分割万物-SAM
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀ 分割万物-SAM 介绍原理分割任务任务预训练zero-shot transfer相关任务 模型Image EncoderPrompt EncoderMask Eecoder消除歧义高效Loss 和训…...
实现RAGFlow-0.14.1的输入框多行输入和消息框的多行显示
一、Chat页面输入框的修改 1. macOS配置 我使用MacBook Pro,chip 是 Apple M3 Pro,Memory是18GB,macOS是 Sonoma 14.6.1。 2. 修改chat输入框代码 目前RAGFlow前端的chat功能,输入的内容是单行的,不能主动使用Shift…...
Pointnet++改进71:添加LFE模块|高效长距离注意力网络
简介:1.该教程提供大量的首发改进的方式,降低上手难度,多种结构改进,助力寻找创新点!2.本篇文章对Pointnet++特征提取模块进行改进,加入LFE模块,提升性能。3.专栏持续更新,紧随最新的研究内容。 目录 1.理论介绍 2.修改步骤 2.1 步骤一 2.2 步骤二 2.3 步骤三 1.理…...
C++STL容器vector容器大小相关函数
目录 前言 主要参考 vector::size vector::max_size vector::resize vector::capacity vector::empty vector::reserve vector::shrink_to_fit 共勉 前言 本文将讨论STL容器vector中与迭代器相关的函数,模板参数T为int类型。 主要参考 cpluscplus.com 侯…...
阿里云CPU超载解决记录
现象:阿里云CPU使用率超90%连续5分钟告警,项目日志error.log中存在heap/gc/limit等内存耗尽等信息,阿里云慢查询日志每日有查询时间很长的参数一直不变的慢sql,linux服务器使用top命令并按c可以看到cpu过大是哪个命令行造成的 分…...
【工具变量】上市公司企业商业信用融资数据(2003-2022年)
一、测算方式:参考《会计研究》张新民老师的做法 净商业信用NTC(应付账款应付票据预收账款)-(应收账款应收票据预付账款),用总资产标准化; 应付账款AP应付账款应付票据预收账款,用总资产标准化 一年以上应付账款比例LAP是企业一年以上(包括一…...
2024数字科技生态大会 | 紫光展锐携手中国电信助力数字科技高质量发展
2024年12月3日至5日,中国电信2024数字科技生态大会在广州举行,通过主题峰会、多场分论坛、重要签约及合作发布等环节,与合作伙伴共绘数字科技发展新愿景。紫光展锐作为中国电信的战略合作伙伴受邀参会,全面呈现了技术、产品创新进…...
ES语法(一)概括
一、语法 1、请求方式 Elasticsearch(ES)使用基于 JSON 的查询 DSL(领域特定语言)来与数据交互。 一个 ElasticSearch 请求和任何 HTTP 请求一样由若干相同的部件组成: curl -X<VERB> <PROTOCOL>://&l…...
(vue)el-cascader多选级联选择器,值取最后一级的数据
(vue)el-cascader多选级联选择器,取值取最后一级的数据 获取到:[“养殖区”,“鸡棚”,“E5001”] 期望:[“E5001”] 问题: 解决方法 增加change事件方法,处理选中的value值 1.单选 <el-cascaderv-model"tags2":o…...
友思特方案 | 精密制程的光影贴合:半导体制造中的高功率紫外光源
导读 为新能源锂电行业赋能第四站:半导体制造中的高功率紫外光源!稳定输出、灵活控制的曝光设备是新能源/半导体行业高端生产中减少误差、提高效率的核心技术,友思特 ALE 系列 UV LED 紫外光源集合6大优势,为精密制造的健康发展提…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
