我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Golang实现验证一个字符串是否为URL

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Golang实现验证一个字符串是否为URL

前言

在实际开发过程中,有时候会遇到 URL 的校验问题,其实我也是直接调用了第三方库,但是也引发了一个思考,Go 语言中有哪些方法去验证一个字符串是否满足 URL 格式呢?

URL 代表唯一资源定位符,是 URI 的子类型(尽管许多人可以互换使用这两个术语)。URL 是对网络资源的引用,通常被视为网址(例如 https://golang.org)。

下面你可以看到一个 URL 的结构,它符合 URI 的结构

URI = scheme:[//authority]path[?query][#fragment]
authority = [userinfo@]host[:port]

官方 URL 包

在 Golang 中利用 url.ParseRequestURI 可以简单验证我们的 URL。

func ParseRequestURI(rawurl string) (*URL, error)

ParseRequestURI 将 rawurl 解析成 URL 结构。它假定在HTTP请求中接收到 rawurl,因此 rawurl 仅被解释为绝对 URI 或绝对路径。假定字符串 rawurl 没有 #fragment 后缀。(Web 浏览器在将 URL 发送到 Web 服务器之前去除 #fragment。)

ParseRequestURI 与 Parse

还有另一种方法应该用于解析 URL 字符串,但有一些注意事项。它允许相对 URL 使验证更加宽松。它是url.Parse

func Parse(rawurl string) (*URL, error)

如文档中所述:

Parse 将 rawurl 解析成 URL 结构。
rawurl 可以是相对的(路径,没有主机)或绝对的(以方案开头)。尝试在没有方案的情况下解析主机名和路径是无效的,但由于解析歧义,不一定会返回错误。

比如如下的例子:

package main

import (
	"fmt"
	"net/url"
)

func main() {

	str := "//yuzhou1u.com"

	var validURL bool

	_, err := url.Parse(str)

	if err != nil {
		fmt.Println(err)
		validURL = false
	} else {
		validURL = true
	}

	fmt.Printf("%s is a valid URL : %v \n", str, validURL)

}

使用 ParseRequestURI

在 Google 解决方法的时候,根据这篇教程中 How to check if a string is a valid URL in Golang? 提供的方法,写了一个函数:

func isValidUrl(u1 string) bool {

	_, err := url.ParseRequestURI(u1)
	if err != nil {
		return false
	}

	u, err := url.Parse(u1)
	if err != nil || u.Scheme == "" || u.Host == "" {
		return false
	}

	// Check if the URL has a valid scheme (http or https)
	if u.Scheme != "http" && u.Scheme != "https" {
		return false
	}

	return true
}

使用这个方法也有个缺陷,如果是多个 schema:https,也是检查不出来的,例如下面的示例:

package main

import (
	"fmt"
	"net/url"
)

func main() {

	fmt.Println(isValidUrl("testURL"))

	fmt.Println(isValidUrl("test.test/"))

	fmt.Println(isValidUrl("http://goglang.org"))

	fmt.Println(isValidUrl("https://goglang.org"))

	fmt.Println(isValidUrl("https://https://https://../google.com"))
}

func isValidUrl(u1 string) bool {

	_, err := url.ParseRequestURI(u1)
	if err != nil {
		return false
	}

	u, err := url.Parse(u1)
	if err != nil || u.Scheme == "" || u.Host == "" {
		return false
	}

	// Check if the URL has a valid scheme (http or https)
	if u.Scheme != "http" && u.Scheme != "https" {
		return false
	}

	return true
}

运行结果如图:

使用 url-verifier 包

安装:go get -u github.com/davidmytton/url-verifier

package main

import (
	"fmt"

	urlverifier "github.com/davidmytton/url-verifier"
)

func main() {

	url := "https://https://https://../google.com"

	verifier := urlverifier.NewVerifier()

	ret, err := verifier.Verify(url)

	if err != nil {
		fmt.Errorf("Error: %s", err)
	}

	fmt.Printf("Result: %+v\n", ret)

}

运行结果:

后面在研究这部分 verifier.go 源码时,发现这个用了 govalidator 这个包,如图:

于是,我们何不直接使用 govalidator 包来判断一个字符串是否是 URL 呢?

使用 govalidator 包

govalidator 是一个针对字符串、结构体和集合的验证器和包。基于 validator.js。

GitHub 地址:github.com/asaskevich/govalidator , 目前收获了 5.7k 的 star

安装:go get github.com/asaskevich/govalidator

package main

import (
	"fmt"

	"github.com/asaskevich/govalidator"
)

func main() {

	str := "https://https://https://../google.com"

	validURL := govalidator.IsURL(str)

	fmt.Printf("%s is a valid URL : %v \n", str, validURL)
}

运行结果如下:

正则表达式匹配

本来想自己写正则表达式匹配的,然后发现 govalidator 包的作者背后的原理也是用了正则表达式的,

然后就偷懒了,直接把他源码中的部分集合到一个 main.go 函数中:

package main

import (
	"fmt"
	"net/url"
	"regexp"
	"strings"
	"unicode/utf8"
)

const (
	URLSchema    string = `((ftp|tcp|udp|wss?|https?):\/\/)`
	URLUsername  string = `(\S+(:\S*)?@)`
	URLPath      string = `((\/|\?|#)[^\s]*)`
	URLPort      string = `(:(\d{1,5}))`
	URLIP        string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3]|24\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-5]))`
	IP           string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
	URLSubdomain string = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))`
	URL                 = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$`

	
	MaxURLRuneCount = 2083
	
	MinURLRuneCount = 3
)

var rxURL = regexp.MustCompile(URL)

// IsURL checks if the string is an URL.
func IsURL(str string) bool {
	if str == "" || utf8.RuneCountInString(str) >= MaxURLRuneCount || len(str) <= MinURLRuneCount || strings.HasPrefix(str, ".") {
		return false
	}
	strTemp := str
	if strings.Contains(str, ":") && !strings.Contains(str, "://") {
		// support no indicated urlscheme but with colon for port number
		// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
		strTemp = "http://" + str
	}
	u, err := url.Parse(strTemp)
	if err != nil {
		return false
	}
	if strings.HasPrefix(u.Host, ".") {
		return false
	}
	if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
		return false
	}
	return rxURL.MatchString(str)
}

func main() {

	fmt.Println(IsURL("testURL"))

	fmt.Println(IsURL("test.test/"))

	fmt.Println(IsURL("http://goglang.org"))

	fmt.Println(IsURL("https://goglang.org"))

	fmt.Println(IsURL("https://https://https://../google.com"))
}

运行结果:

除了校验 URL,这个包还提供了众多的字符串校验方法,例如校验邮箱、信用卡格式、IP...

总结

数据校验是每个程序员日常开发过程的一部分,尤其是在从事后端服务时,数据验证必须严格,保持正确。

在这篇文章中,我们讨论了如何在 Go 语言中正确验证一个字符串是否是 URL,当然利用了官方包和优秀的第三方包,在实际过程中,可能我们为了简便会直接使用别人开发好的工具,但是在学习过程中,不妨也去思考别人实现的原理,结合实际业务需要,进而扩展成自己的工具包。

以上就是Golang实现验证一个字符串是否为URL的详细内容,更多关于Golang验证字符串是否为URL的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Golang实现验证一个字符串是否为URL

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Golang实现验证一个字符串是否为URL

在实际开发过程中,有时候会遇到 URL 的校验问题,Go 语言中有哪些方法去验证一个字符串是否满足 URL 格式呢?本文就来和大家详细讲讲
2023-05-16

如何利用php验证字符串是否为数字

这篇文章主要介绍如何利用php验证字符串是否为数字,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!第一种方法:利用函数is_numeric()验证 bool is_numeric ( mixed $var )$v
2023-06-14

Golang字符串结尾字符验证的实现方式

标题:Golang字符串结尾字符验证的实现方式在Golang中,我们经常需要对字符串进行各种操作和验证,其中之一就是验证字符串是否以特定字符结尾。在本文中,我们将介绍如何使用Golang实现字符串结尾字符的验证,并提供具体的代码示例。首
Golang字符串结尾字符验证的实现方式
2024-03-12

php如何验证字符串第一个字符是不是指定值

这篇文章主要介绍了php如何验证字符串第一个字符是不是指定值的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇php如何验证字符串第一个字符是不是指定值文章都会有所收获,下面我们一起来看看吧。3种方法:1、用“st
2023-06-30

如何使用Golang判断一个字符是否为字母

如何使用Golang判断一个字符是否为字母在Golang中,判断一个字符是否为字母可以通过使用Unicode包中的IsLetter函数来实现。IsLetter函数会检查给定的字符是否是一个字母。接下来,我们将详细介绍如何使用Golang编写
如何使用Golang判断一个字符是否为字母
2023-12-23

java怎么判断一个字符串是否为回文

可以用以下几种方法来判断一个字符串是否为回文:1. 使用 StringBuilder 类的 reverse 方法将字符串反转,然后与原字符串进行比较。如果相等,则为回文。javapublic static boolean isPalindr
2023-10-18

c++怎么判断一个字符串是否为回文

在C++中,可以通过以下方法来判断一个字符串是否为回文:使用双指针法:定义两个指针,一个指向字符串的开头,一个指向字符串的末尾。分别向中间移动指针,判断对应的字符是否相等,如果有一个不相等,则不是回文。bool isPalindrome(s
c++怎么判断一个字符串是否为回文
2024-02-29

使用Golang判断一个字符是否为字母的方法

Golang实现:判断字符是否为字母的方法在Golang中,有多种方法可以判断一个字符是否为字母。本文将介绍其中几种常用的方法,并为每种方法提供具体的代码示例。方法一:使用Unicode包的IsLetter函数Golang中的Unicode
使用Golang判断一个字符是否为字母的方法
2023-12-23

Golang 中怎么判断字符串是否在一个数组中

Golang 中怎么判断字符串是否在一个数组中,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在使用 Python 的时候,如果要判断一个字符串是否在另一个包含字符串的列表中
2023-06-16

Python实现判断一个字符串是否包含子串的方法总结

本文实例总结了Python实现判断一个字符串是否包含子串的方法。分享给大家供大家参考,具体如下: 1.使用成员操作符 in>>> s='nihao,shijie' >>> t='nihao' >>> result = t in s >>>
2022-06-04

Shell判断字符串变量是否为空的方法实现

目录Bash Shell 判断一个变量是否为空检查bash shell变量是否为空的另一个方式您可以将 -z 选项传递给 if 命令或条件表达式。如果STRING的长度为0,variable ($var)为空。t
2022-06-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录