gin框架教程笔记

参考

官方中文文档:https://gin-gonic.com/zh-cn/docs/introduction/ 但是示例截图少
https://www.kancloud.cn/shuangdeyu/gin_book/949411
https://www.topgoer.com/gin%E6%A1%86%E6%9E%B6/ 这个网站不光有gin框架 适合阅读

吉米老师的 :https://www.liwenzhou.com/posts/Go/Gin_framework/
他的其他链接:https://www.liwenzhou.com/posts/Go/golang-menu/
docker部署go项目:https://www.liwenzhou.com/posts/Go/how_to_deploy_go_app_using_docker/

官方网站:https://gin-gonic.github.io/gin/
Github地址:https://github.com/gin-gonic/gin

什么是框架

框架是指半成品的应用,一般需要填充少许代码或者无需填充代码就可以运行,只是这样的应用缺少业务逻辑。

我们使用框架开发,主要工作就是在框架上补充业务逻辑代码。所以,借助框架进行开发,不仅可以减少开发时间、提高效率,也有助于团队统一编码风格,形成 编程规范。

gin 框架是一个 Web 框架,它封装了 路由、Cookie、Session、参数处理、数据编解码以及中间件等功能,简单高效,降低了开发 Web 应用的难度。

gin 是一个使用 Go 语言编写的 Web 后端框架,具有简洁、轻量、支持高并发、封装优雅、API 友好、快速灵活、容错方便等特点。

gin 和 beego 是 Go 语言编写 Web 应用最常用的后端框架。

使用 Go 语言开发 Web 应用,对于框架的依赖要比其它编程语言要小。Go 语言内置的 net/http 包简单轻便,性能优良。而且,大多数的 Go 语言 Web 框架都是在其之上进行的封装。

安装与导入

$ go get -u github.com/gin-gonic/gin
import ("net/http" //通常还需要导入 net/http 包,因为代码中一般需要一些常量,比如返回码 http.StatusOK。"github.com/gin-gonic/gin"
)

在这里插入图片描述

学学这个排版。

Hello World

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 1.创建路由engine := gin.Default()// 2.绑定路由规则,执行的函数,这里写成了匿名函数的形式 也可单独写一个函数// gin.Context,封装了request和response//指定对什么网址进行相应,响应什么内容engine.GET("/", func(c *gin.Context) {c.String(http.StatusOK, "Hello World!")})// 3.监听端口,默认在8080engine.Run()//相当于 engine.Run(":8080")
}

上面GET方法可拆为:

helloHandler := func(context *gin.Context) {context.String(http.StatusOK, "Hello World!")
}
func main() {//···省略engine.GET("/",helloHandler)
}

//GET is a shortcut for router.Handle("GET", path, handle)
helloHandler := func(context *gin.Context) {fmt.Fprint(context.Writer, "Hello World!")
}
r.Handle("GET", "/hello", helloHandler)

打开浏览器,输入 http://localhost:8080,就可以看到浏览器输出:

Hello World!

如果我们不使用gin框架,原生的go也可以实现:
在这里插入图片描述

路由处理

什么是路由

在web开发中,“route”是指根据url分配到对应的处理程序。

路由(route)就是根据 HTTP 请求的 URL,设置由哪个函数来处理请求。路由是 Web 框架的核心功能。

路由通常这样实现:根据路由里的字符 “/”,把路由切分成多个字符串数组,然后构造成树状结构;寻址的时候,先把请求的 URL 按照 “/” 进行切分,然后遍历树进行寻址。

比如:定义了两个路由 /user/get,/user/delete,则会构造出拥有三个节点的路由树,根节点是 user,两个子节点分别是 get 和 delete。

gin 框架路由库

gin 框架中采用的路由库是基于 httprouter 开发的。
httprouter 项目地址:https://github.com/julienschmidt/httprouter。

gin 框架路由的范例

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()// 下面是两条路由engine.GET("/", func(c *gin.Context) {c.String(http.StatusOK, "编程教程")})engine.GET("/hello", func(c *gin.Context) {c.String(http.StatusOK, "Hello World")})// 监听端口默认为8080engine.Run(":8080")
}

运行程序,然后打开浏览器,输入 http://localhost:8080/,可以看到浏览器输出:编程教程。然后输入 http://localhost:8080/hello,可以看到浏览器输出:Hello World。

r.GET("/a",func(c *gin.Context) {})
r.POST("/b",func(c *gin.Context) {})
//此外,还有一个可以匹配所有请求方法的Any方法如下
r.Any("/c",func(c *gin.Context) {})

RESTAPI

web 应用程序,一般分为前端和后端两个部分。前后端通信通常需要一种统一机制,以方便不同的前端设备与后端进行通信。这种需求导致了 API 构架的流行,甚至出现 “API First” 的设计思想。

RESTful API 是目前比较成熟的一套 web 应用程序的 API 设计理论,用于 web 前后端的数据交互。

RESTful API 路径

RESTful API 的路径又称 “终点”(endpoint),表示 API 的具体网址。

在 RESTful 架构中,每个网址代表一种资源(resource),比如:有一个 API 提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样:

https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees

RESTful API HTTP 动词

在 RESTful API 设计理论中,对于资源的操作,由 HTTP 动词表示。

常用的 HTTP 动词有下面五个(括号里是对应的数据库 SQL 命令)。

  • GET(SELECT):从服务器取出资源(一项或多项)。
  • POST(CREATE):在服务器新建一个资源。
  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
  • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
  • DELETE(DELETE):从服务器删除资源。

还有两个不常用的HTTP动词。

  • HEAD:获取资源的元数据。
  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

比如

  • GET /zoos:列出所有动物园
  • POST /zoos:新建一个动物园
  • GET /zoos/ID:获取某个指定动物园的信息
  • PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
  • PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
  • DELETE /zoos/ID:删除某个动物园
  • GET /zoos/ID/animals:列出某个指定动物园的所有动物
  • DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

下面是一些例子

gin 框架支持 RESTful 风格的 API。

RESTful 即 Representational State Transfer 的缩写。直接翻译的意思是 “表现层状态转化”,是一种互联网应用程序的API设计理念:URL 定位资源,用 HTTP 方法描述操作,例如:

  1. 获取文章 /blog/getXxx Get blog/Xxx
  2. 添加文章 /blog/addXxx POST blog/Xxx
  3. 修改文章 /blog/updateXxx PUT blog/Xxx
  4. 删除文章 /blog/delXxxx DELETE blog/Xxx

在这里插入图片描述

gin 框架路由的基本语法

Gin 的路由支持 HTTP 的 GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS 方法的请求,同时还有一个 Any 函数,可以同时支持以上的所有请求。

Gin 的路由通常的使用方法如下:

// 获取默认的 gin Engine,Engine 中包含了所有路由处理的接口
engine := gin.Default()// Get 请求路由
engine.GET("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin get method")
})
// Post 请求路由
engine.POST("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin post method")
})
// Put 请求路由 
engine.PUT("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin put method")
})
// Delete 请求路由
engine.DELETE("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin delete method")
})
// Patch 请求路由
engine.PATCH("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin patch method")
})
// Head 请求路由
engine.HEAD("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin head method")
})
// Options 请求路由
engine.OPTIONS("/", func(context *gin.Context) {context.String(http.StatusOK, "hello gin options method")
})

gin路由分组

我们在使用 web 框架开发时,经常会根据业务逻辑给一个模块划分一组路由。

把一个模块相关的方法都写在一个路由下,主要好处是业务逻辑清晰,便于管理和查找相关的代码。

例如:goods 为商品模块,我们规划它的操作路由。

/goods/addGoods 添加商品
/goods/delGoods 删除商品

gin 框架支持路由分组(routes group),路由分组的关键词为 group。

engine.Group("/groupname")

写法1

package mainimport ("fmt""github.com/gin-gonic/gin"
)func loginEndpoint(c *gin.Context){fmt.Println("这是login方法")
}func submitEndpoint(c *gin.Context){fmt.Println("这是submit方法")
}func readEndpoint(c *gin.Context){fmt.Println("这是read方法")
}func main() {engine := gin.Default()//v1组路由     // {} 是书写规范  这个语法是咋实现的?  是函数先返回一个结构体 再实例化的意思么?v1 := engine.Group("/v1"){v1.GET("/login", loginEndpoint)v1.GET("/submit", submitEndpoint)v1.GET("/read", readEndpoint)}//v2组路由v2: = engine.Group("/v2"){v2.GET("/login", loginEndpoint)v2.GET("/submit", submitEndpoint)v2.GET("/read", readEndpoint)}engine.Run()
}

打开浏览器,输入 http://localhost:8080,分别访问:

http://localhost:8080/v1/login
http://localhost:8080/v1/submit
http://localhost:8080/v1/read
http://localhost:8080/v2/login
http://localhost:8080/v2/submit
http://localhost:8080/v2/read

浏览器会输出对应的 API 内容。

写法2

也可以这样:

func main() {r := gin.Default()user := r.Group("/user")user.GET("/index", func(c *gin.Context) {})user.POST("/login", func(c *gin.Context) {})r.Run()
}

在这里插入图片描述
区别,就在于不用再单独写路由了

参数处理

web 程序中经常需要处理各种形式的参数,参数是处理 HTTP 请求中很重要的工作,它是前端向后端提交数据的基本形式。

gin 框架内置了处理 HTTP 各种参数的方法,包括 API 参数,URL 参数 以及 表单参数的处理。

query参数处理(URL 参数处理)(get)

例如​/name=admin&pwd=123456​,我们想得到name和pwd的值

URL 参数可以通过 DefaultQuery() 或 Query() 方法获取。
DefaultQuery() 若参数不存在,则返回默认值,Query()若不存在,返回空串。

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {name := c.DefaultQuery("name", "admin")pwd := c.Query("pwd")// fmt.Printf("name:%s ; pwd:%s",name,pwd)c.JSON(http.StatusOK, gin.H{"name": name,"pwd":  pwd,})})r.Run()
}

表单Form参数处理 (post)

表单传输为post请求,http常见的传输格式为四种:

application/json
application/x-www-form-urlencoded
application/xml
multipart/form-data

表单参数可以通过 PostForm() 方法获取,该方法默认解析的是 x-www-form-urlencoded 或 from-data 格式的参数。

package mainimport ("fmt""net/http""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()engine.POST("/form", func(c *gin.Context) {types := c.DefaultPostForm("type", "post")username := c.PostForm("username")password := c.PostForm("userpassword")c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))})engine.Run()
}

从表单中获取了 types、username、password 三个参数。

API 参数处理

gin 框架中,可以通过 Context 的 Param 方法来获取 API 参数。

比如:提取 http://localhost:8080/user/zhangsan 的参数 zhangsan。

package mainimport ("net/http""strings""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()engine.GET("/user/:name", func(c *gin.Context) {name := c.Param("name")c.String(http.StatusOK, "name=" + name)})// 监听8080端口engine.Run(":8080")
}

运行程序,浏览器中输入:http://localhost:8080/user/zhangsan,浏览器会输出:name=zhangsan。

/user/:name/*action 这种也是api参数 后面会再讲

上传文件

简单来说 就是

FormFile("文件名")
<input type="file" name="file" >

上传单个文件

gin 框架中,multipart/form-data 格式用于文件上。

文件上传与原生的 net/http 方法类似,不同在于 gin 把原生的 request 封装到 c.Request 中。

前端 html 文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">上传文件:<input type="file" name="file" ><input type="submit" value="提交"></form>
</body>
</html>

文件可以保存为 test.html。

后端 go 文件:

package mainimport ("github.com/gin-gonic/gin"
)func main() {engine := gin.Default()//限制上传最大尺寸engine.MaxMultipartMemory = 8 << 20engine.POST("/upload", func(c *gin.Context) {file, err := c.FormFile("file")if err != nil {c.String(500, "上传图片出错")}// c.JSON(200, gin.H{"message": file.Header.Context})c.SaveUploadedFile(file, file.Filename)c.String(http.StatusOK, file.Filename)})engine.Run()
}

运行程序后,浏览器访问 test.html文件,就可以在浏览器中上传文件。

OR

前端页面代码

<!DOCTYPE html>
<html lang="zh-CN">
<head><title>上传文件示例</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data"><input type="file" name="f1"><input type="submit" value="上传">
</form>
</body>
</html>

后端Gin框架部分代码

package mainimport ("fmt""log""net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 处理multipart forms提交文件时默认的内存限制是32 MiB// 可以通过下面的方式修改// r.MaxMultipartMemory = 8 << 20  // 8 MiBr.POST("/upload", func(c *gin.Context) {// 单个文件file, err := c.FormFile("f1")if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}log.Println(file.Filename)dst := fmt.Sprintf("C:/tmp/%s", file.Filename)// 上传文件到指定的目录c.SaveUploadedFile(file, dst)c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("'%s' uploaded!", file.Filename),})})r.Run()
}

上传特定文件

有的用户上传文件需要限制上传文件的类型以及上传文件的大小,但是 gin 框架暂时没有这些函数。因此,我们基于原生的函数写了一个可以限制大小以及文件类型的上传函数。

package mainimport ("fmt""log""net/http""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()engine.POST("/upload", func(c *gin.Context) {_, headers, err := c.Request.FormFile("file")if err != nil {log.Printf("Error when try to get file: %v", err)}//headers.Size 获取文件大小if headers.Size > 1024*1024*2 {fmt.Println("文件太大了")return}//headers.Header.Get("Content-Type")获取上传文件的类型if headers.Header.Get("Content-Type") != "image/png" {fmt.Println("只允许上传png图片")return}c.SaveUploadedFile(headers, "./video/"+headers.Filename)c.String(http.StatusOK, headers.Filename)})engine.Run()
}

上传多个文件

前端 html 文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">上传文件:<input type="file" name="files" multiple><input type="submit" value="提交"></form>
</body>
</html>

文件可以保存为 test.html。

package mainimport ("github.com/gin-gonic/gin""net/http""fmt"
)func main() {engine := gin.Default()// 限制表单上传大小 8MB,默认为32MBengine.MaxMultipartMemory = 8 << 20engine.POST("/upload", func(c *gin.Context) {form, err := c.MultipartForm()if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))}// 获取所有图片files := form.File["files"]// 遍历所有图片for _, file := range files {// 逐个保存if err := c.SaveUploadedFile(file, file.Filename); err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))return}}c.String(200, fmt.Sprintf("upload ok %d files", len(files)))})engine.Run()
}

运行程序后,浏览器访问 test.html文件,就可以在浏览器中上传文件。

OR

package mainimport ("fmt""log""net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 处理multipart forms提交文件时默认的内存限制是32 MiB// 可以通过下面的方式修改// r.MaxMultipartMemory = 8 << 20  // 8 MiBr.POST("/upload", func(c *gin.Context) {// Multipart formform, _ := c.MultipartForm()files := form.File["file"]for index, file := range files {log.Println(file.Filename)dst := fmt.Sprintf("C:/tmp/%s_%d", file.Filename, index)// 上传文件到指定的目录c.SaveUploadedFile(file, dst)}c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("%d files uploaded!", len(files)),})})r.Run()
}

中间件

Gin框架允许开发者在处理请求的过程中,加入钩子函数,这个钩子函数就叫中间件。中间件适合处理一些公共的业务逻辑,比如登陆认证,权限校验,记录日志等。具体使用方法如下

package mainimport ("fmt""net/http""time""github.com/gin-gonic/gin"
)//定义一个中间键m1统计请求处理函数耗时
func m1(c *gin.Context) {fmt.Println("m1 in...")start := time.Now()// c.Next() //调用后续的处理函数c.Abort()//阻止调用后续的处理函数cost := time.Since(start)fmt.Printf("cost:%v\n", cost)
}func index(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "ok",})
}func main() {r := gin.Default()r.GET("/", m1, index)  //之前没有中间件的写法r.GET("/", index)r.Run()
}

还没找到分类

func main() {r := gin.Default()// gin.H 是map[string]interface{}的缩写r.GET("/someJSON", func(c *gin.Context) {// 方式一:自己拼接JSONc.JSON(http.StatusOK, gin.H{"message": "Hello world!"})})r.GET("/moreJSON", func(c *gin.Context) {// 方法二:使用结构体var msg struct {Name    string `json:"user"`Message stringAge     int}msg.Name = "小王子"msg.Message = "Hello world!"msg.Age = 18c.JSON(http.StatusOK, msg)})r.Run(":8080")
}

其中 方法一 等价
在这里插入图片描述
注意,结构体方法,变量名要大写。所以用tag

template

在一些前后端不分离的Web架构中,我们通常需要在后端将一些数据渲染到HTML文档中,从而实现动态的网页(网页的布局和样式大致一样,但展示的内容并不一样)效果。

我们这里说的模板可以理解为事先定义好的HTML文档文件,模板渲染的作用机制可以简单理解为文本替换操作–使用相应的数据去替换HTML文档中事先准备好的标记。

可以看这个:https://www.liwenzhou.com/posts/Go/go_template/

插件推荐

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

88. 合并两个有序数组 (Swift版本)

题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并…

软考高级:决策支持系统 DSS 概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

x86_64架构栈帧以及帧指针FP

文章目录 一、x86_64架构寄存器简介二、x86_64架构帧指针FP三、示例四、保存帧指针参考资料 一、x86_64架构寄存器简介 在x86架构中&#xff0c;有8个通用寄存器可用&#xff1a;eax、ebx、ecx、edx、ebp、esp、esi和edi。在x86_64&#xff08;x64&#xff09;扩展中&#xff…

Redis开发规范与性能优化(二)

开发规范与性能优化 3.客户端使用 1.【推荐】避免多个应用使用一个Redis示例 正例:不相干的业务拆分&#xff0c;公共数据库做服务化 2.【推荐】使用带有连接池的数据库&#xff0c;可以有效控制链接&#xff0c;同时提高效率&#xff0c;标准使用方式如代码所示 public c…

CSS Module

CSS Module的作用&#xff1a;将CSS样式作用域限制在特定的组件范围内&#xff0c;以避免全局样式污染和命名冲突。 Vue中如何实现样式模块…

ideaSSM社区二手交易平台C2C模式开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea ssm 社区二手交易平台系统是一套完善的完整信息管理系统&#xff0c;结合SSM框架完成本系统SpringMVC spring mybatis &#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码…

java的23种设计模式02-创建型模式02-抽象工厂方法

一、抽象工厂方法 1-1、抽象工厂方法的定义 抽象工厂模式是一个比较复杂的创建型模式。 抽象工厂模式和工厂方法不太一样&#xff0c;它要解决的问题比较复杂&#xff0c;不但工厂是抽象的&#xff0c;产品是抽象的&#xff0c;而且&#xff1a;有多个产品需要创建&#xff…

unity3d Animal Controller的Animal组件中Stances,Advanced基础部分理解

Stances 立场 立场要求在动物动画控制器上的姿态动画参数。 你可以有多个运动状态,并根据当前的立场使用它们 过渡的条件是: Stance StanceID Default Stance默认姿势 如果调用函数Stance_Reset&#xff08;&#xff09;&#xff0c;动物将返回到的默认姿势。 Current …

Oracle Primavera P6 Analytics 是什么,与P6的关系?

前言 Oracle Primavera P6 Analytics 是与P6有关的一个相对较新的模块&#xff0c;Primavera 用户社区在很大程度上尚未对其进行探索。 那么它到底有什么作用呢&#xff1f; 通过了解得知它旨在通过深入了解组织的项目组合绩效&#xff0c;帮助高级管理层对其项目组合做出更好…

【设计模式】二、UML 类图与面向对象设计原则 之 UML概述

二、UML 类图与面向对象设计原则 &#xff08;一&#xff09;UML 类图 UML 概述类与类的UML图示类之间的关系 &#xff08;二&#xff09;面向对象设计原则 单一职责原则&#xff08;Single Responsibility Principle, SRP&#xff09;开闭原则&#xff08;Open-Closed Princip…

[数据集][目标检测]零售柜零食检测数据集VOC+YOLO格式5422张113类

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;5422 标注数量(xml文件个数)&#xff1a;5422 标注数量(txt文件个数)&#xff1a;5422 标注…

Linux ping可以上内网,不能上外网(系统重启DNS不生效)(直接更改/etc/resolv.conf修改nameserver重启被重置)

在Linux上可以连内网&#xff0c;不能连外网 ping内网可以&#xff0c;外网不行 可能的问题&#xff1a; 1.可能设置了网络防火墙&#xff0c;阻止了服务器访问外网的请求 2.DNS解析问题&#xff1a;检查服务器的DNS设置是否正确&#xff0c;能够正确解析外部域名。如果DNS解析…