大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
本教程介绍了 Go 中模糊测试的基础知识。通过模糊测试,随机数据会针对您的测试运行,以尝试找出漏洞或导致崩溃的输入。可以通过模糊测试发现的一些漏洞示例包括 SQL 注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。
我们提供的服务有:成都做网站、成都网站制作、微信公众号开发、网站优化、网站认证、大余ssl等。为上1000家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的大余网站制作公司
在本教程中,您将为一个简单的函数编写一个模糊测试,运行 go 命令,并调试和修复代码中的问题。
首先,为您要编写的代码创建一个文件夹。
1、打开命令提示符并切换到您的主目录。
在 Linux 或 Mac 上:
在 Windows 上:
2、在命令提示符下,为您的代码创建一个名为 fuzz 的目录。
3、创建一个模块来保存您的代码。
运行go mod init命令,为其提供新代码的模块路径。
接下来,您将添加一些简单的代码来反转字符串,稍后我们将对其进行模糊测试。
在此步骤中,您将添加一个函数来反转字符串。
a.使用您的文本编辑器,在 fuzz 目录中创建一个名为 main.go 的文件。
独立程序(与库相反)始终位于 package 中main。
此函数将接受string,使用byte进行循环 ,并在最后返回反转的字符串。
此函数将运行一些Reverse操作,然后将输出打印到命令行。这有助于查看运行中的代码,并可能有助于调试。
e.该main函数使用 fmt 包,因此您需要导入它。
第一行代码应如下所示:
从包含 main.go 的目录中的命令行,运行代码。
可以看到原来的字符串,反转它的结果,然后再反转它的结果,就相当于原来的了。
现在代码正在运行,是时候测试它了。
在这一步中,您将为Reverse函数编写一个基本的单元测试。
a.使用您的文本编辑器,在 fuzz 目录中创建一个名为 reverse_test.go 的文件。
b.将以下代码粘贴到 reverse_test.go 中。
这个简单的测试将断言列出的输入字符串将被正确反转。
使用运行单元测试go test
接下来,您将单元测试更改为模糊测试。
单元测试有局限性,即每个输入都必须由开发人员添加到测试中。模糊测试的一个好处是它可以为您的代码提供输入,并且可以识别您提出的测试用例没有达到的边缘用例。
在本节中,您将单元测试转换为模糊测试,这样您就可以用更少的工作生成更多的输入!
请注意,您可以将单元测试、基准测试和模糊测试保存在同一个 *_test.go 文件中,但对于本示例,您将单元测试转换为模糊测试。
在您的文本编辑器中,将 reverse_test.go 中的单元测试替换为以下模糊测试。
Fuzzing 也有一些限制。在您的单元测试中,您可以预测Reverse函数的预期输出,并验证实际输出是否满足这些预期。
例如,在测试用例Reverse("Hello, world")中,单元测试将返回指定为"dlrow ,olleH".
模糊测试时,您无法预测预期输出,因为您无法控制输入。
但是,Reverse您可以在模糊测试中验证函数的一些属性。在这个模糊测试中检查的两个属性是:
(1)将字符串反转两次保留原始值
(2)反转的字符串将其状态保留为有效的 UTF-8。
注意单元测试和模糊测试之间的语法差异:
(3)确保新包unicode/utf8已导入。
随着单元测试转换为模糊测试,是时候再次运行测试了。
a.在不进行模糊测试的情况下运行模糊测试,以确保种子输入通过。
如果您在该文件中有其他测试,您也可以运行go test -run=FuzzReverse,并且您只想运行模糊测试。
b.运行FuzzReverse模糊测试,查看是否有任何随机生成的字符串输入会导致失败。这是使用go test新标志-fuzz执行的。
模糊测试时发生故障,导致问题的输入被写入将在下次运行的种子语料库文件中go test,即使没有-fuzz标志也是如此。要查看导致失败的输入,请在文本编辑器中打开写入 testdata/fuzz/FuzzReverse 目录的语料库文件。您的种子语料库文件可能包含不同的字符串,但格式相同。
语料库文件的第一行表示编码版本。以下每一行代表构成语料库条目的每种类型的值。由于 fuzz target 只需要 1 个输入,因此版本之后只有 1 个值。
c.运行没有-fuzz标志的go test; 新的失败种子语料库条目将被使用:
由于我们的测试失败,是时候调试了。
go语言的字符串是UTF-8编码的、不可改变的字节序列。
要修改字符串,只能以原串为基础,创建一个新串。下面的图中是一个参考示例,提供了以原串为蓝本,创建新串的两种方法。
代码
输出
事实上,如果列入Java,那么React、jQuery等等,或者其他多种软件包或框架也都需要被列入进来,然而这些显然会在未来几年中逐步更新换代的。考虑到篇幅所限就不多叙述别的知识了。)
1.Go语言
今年10月的TIOBE编程语言人气榜上,Go语言得到了简单但有力的描述:“谷歌的Go语言几乎无可匹敌,而这主要是受到Docker等Go语言编写的容器应用方案的大力推动。”
尽管Go语言最初的目的有实验性质,但Docker以及其它企业都把它作为自身基础设施的有力支柱,而理由则非常简单:它拥有迅如闪电的编译与执行速度,可以使用简单方法(Goroutines)支持并发机制,并且也为程序员们提供大量选项来构建并维护现有及新型技术。然而Go语言的好处需要到代码量达到一定量之后才能体会出来,比如当你遇见一个cpp文件一个小时都编译不完的时候,你就知道简化语法增加编译速度有多重要了。Go同样面向对象,但它不存在类型结构。
以下为Go语言中的“Hello World”编写方式:
package main import "fmt" func main() { fmt.Println("Hello, World") }
2.Rust
与火狐浏览器同宗同源的Rust是一类系统编程语言,它运行速度极快、不存在段错误并且可以保障安全。与Go不同,Rust并不具备垃圾回收机制(Go的垃圾回收机制速度很快),因此Rust编程适用于嵌入式系统。
与Go类似,Rust依赖于代码分支结构——但Rust更为复杂。两种语言都是免费,并且它们都拥有自己的支持工具生态系统。Rust博客主页中的“稳定性即可交付性”口号正是Rust的理念所在; 其在RedMonkt及其它编程语言榜单上皆拥有不俗表现,其未来发展自然值得关注。
下面来看一段出色的Rust代码示例:
let number = 13; println!("Tell me about {}", number); match number { // Match a single value 1 = println!("One!"), // Match several values 2 | 3 | 5 | 7 | 11 = println!("This is a prime"), // Match an inclusive range 13...19 = println!("A teen"), // Handle the rest of cases _ = println!("Ain't special"), } let boolean = true; // Match is an expression too let binary = match boolean { // The arms of a match must cover all the possible values false = 0, true = 1, }; println!("{} - {}", boolean, binary); }
3.Git
时至今日,每个人都需要使用版本控制系统(简称VCS)。VCS实际上就是一套容纳代码及数据的存储库。它能够追踪变更,并使用开源meld等diff工具进行变更查看。
各类VCS的工作原理大体相同。大家需要利用源代码文件建立一个项目,而后即可随时对其进行检查、编辑而后确认(提交)。
由Linux之父Linus Torvalds编写的Git是一套分布式VCS,因此其可供团队成员以远程方式使用各自的文件进行编辑,而后将变更的结果进行合并。如果存在冲突,也就是两位成员对同一文件提交了不同编辑结果,Git则会在合并时以高亮方式显示冲突部分。接着,大家必须手动编辑并修改这些内容。从人气角度讲,Git已然所向披靡。
4.HTML
在今天探讨的四种技术中,HTML显然最为简单。HTML是网页标记语言,是浏览器能够阅读的语言。只要你写的东西想要浏览器能正确显示出来,那就要懂HTML。其中的/代表着关闭标签,而且大多数HTML标签都利用这种开放标签加/关闭标签的形式起效。(对于以HTML起始的内容,标头可选且为文档中的不可见部分,而本体则容纳可见部分。)
大多数其它HTML标签用于实现布局与文本格式; 其同样易于使用。尽管HTML的技术标准已经相当陈旧,但其仍然被广泛使用——如果大家尚不了解,请一定找点时间进行学习。
5.Python
如果,只能选择掌握一种编程语言,那么我的答案是Python。早在互联网诞生之前,Basic是每一位开发者所必须了解的语言选项; 如今Python就是新时代下的Basic。这是一种通用型编程语言,虽然没人会利用其编写那些“重量级”应用——例如游戏或者操作系统(这类应用仍然使用C++)。
Python易于学习,且使用缩进而非大括号标记结构。以下代码来自Python维基词条:
parents, babies = (1, 1) while babies 100: print 'This generation has {0} babies'.format(babies) parents, babies = (babies, parents + babies)
Python语言带有解释特性,因此大家可以在Python shell中尝试各种命令丈表达式。其速度很快,但相比优化型编译语言稍慢一点。它拥有规模庞大的资源库,且可通过多种方式实现进一步提速。大家可以使用pypy等替代性方案或者利用Cython将其编译为C; 如果大家了解C语言,也能够编写自己的C、Go或者Rust扩展。
Python在科学家群体中亦大受欢迎。最近推出的英特尔Python(免费)使得Python成为一种面向机器学习的可用语言,其适用场景包括大数据、神经网络以及其它相关技术。英特尔打造的这套发行版包含超过100套软件包(NumPy、SciPy等),且专门进行了优化以使用英特尔MKL及英特尔TBB库——二者内置于其中且可免费使用。大部分高强度任务都可由这些经过优化的英特尔库负责执行。
6.Linux
即使大家身为专业Windows用户及程序员,Linux同样值得加以关注,它能帮助您更快地学习,它还能使用多种技术方案。举例来说,Python、Go以及Rust就更适合在Linux平台上使用。(要在Windows上进行Rust程序编译,大家需要使用微软VC++或者MinGW——这是一套GNU编译器与工具集合,专门用于Windows平台上的开发与运行任务)。
对于Windows用户,大家只需要下载免费VirtualBox并安装一套Linux发行版(我个人推荐Ubuntu 14.04 LTS或者16.04 LTS)即可开始Linux之旅。在此之后,大家即可学习Linux,安装各类编程语言,运行本地LAMP(Linux Apache MySQL PHP)Web服务器甚至尝试进行开发工作。
英文原文链接【Go, the unwritten parts】 发表于2017/05/22 作者JBD是Go语言开发小组成员
检查程序的执行路径和当前状态是非常有用的调试手段。核心文件(core file)包含了一个运行进程的内存转储和状态。它主要是用来作为事后调试程序用的。它也可以被用来查看一个运行中的程序的状态。这两个使用场景使调试文件转储成为一个非常好的诊断手段。我们可以用这个方法来做事后诊断和分析线上的服务(production services)。
在这篇文章中,我们将用一个简单的hello world网站服务作为例子。在现实中,我们的程序很容易就会变得很复杂。分析核心转储给我们提供了一个机会去重构程序的状态并且查看只有在某些条件/环境下才能重现的案例。
作者注 : 这个调试流程只在Linux上可行。我不是很确定它是否在其它Unixs系统上工作。macOS对此还不支持。Windows现在也不支持。
在我们开始前,需要确保核心转储的ulimit设置在合适的范围。它的缺省值是0,意味着最大的核心文件大小是0。我通常在我的开发机器上将它设置成unlimited。使用以下命令:
接下来,你需要在你的机器上安装 delve 。
下面我们使用的 main.go 文件。它注册了一个简单的请求处理函数(handler)然后启动了HTTP服务。
让我们编译并生产二进制文件。
现在让我们假设,这个服务器出了些问题,但是我们并不是很确定问题的根源。你可能已经在程序里加了很多辅助信息,但还是无法从这些调试信息中找出线索。通常在这种情况下,当前进程的快照会非常有用。我们可以用这个快照深入查看程序的当前状态。
有几个方式来获取核心文件。你可能已经熟悉了奔溃转储(crash dumps)。它们是在一个程序奔溃的时候写入磁盘的核心转储。Go语言在缺省设置下不会生产奔溃转储。但是当你把 GOTRACEBACK 环境变量设置成“crash”,你就可以用 Ctrl+backslash 才触发奔溃转储。如下图所示:
上面的操作会使程序终止,将堆栈跟踪(stack trace)打印出来,并把核心转储文件写入磁盘。
另外个方法可以从一个运行的程序获得核心转储而不需要终止相应的进程。 gcore 可以生产核心文件而无需使运行中的程序退出。
根据上面的操作,我们获得了转储而没有终止对应的进程。下一步就是把核心文件加载进delve并开始分析。
差不多就这些。delve的常用操作都可以使用。你可以backtrace,list,查看变量等等。有些功能不可用因为我们使用的核心转储是一个快照而不是正在运行的进程。但是程序执行路径和状态全部可以访问。
本文介绍一些Go语言的基础语法。
先来看一个简单的go语言代码:
go语言的注释方法:
代码执行结果:
下面来进一步介绍go的基础语法。
go语言中格式化输出可以使用 fmt 和 log 这两个标准库,
常用方法:
示例代码:
执行结果:
更多格式化方法可以访问中的fmt包。
log包实现了简单的日志服务,也提供了一些格式化输出的方法。
执行结果:
下面来介绍一下go的数据类型
下表列出了go语言的数据类型:
int、float、bool、string、数组和struct属于值类型,这些类型的变量直接指向存在内存中的值;slice、map、chan、pointer等是引用类型,存储的是一个地址,这个地址存储最终的值。
常量是在程序编译时就确定下来的值,程序运行时无法改变。
执行结果:
执行结果:
Go 语言的运算符主要包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符以及指针相关运算符。
算术运算符:
关系运算符:
逻辑运算符:
位运算符:
赋值运算符:
指针相关运算符:
下面介绍一下go语言中的if语句和switch语句。另外还有一种控制语句叫select语句,通常与通道联用,这里不做介绍。
if语法格式如下:
if ... else :
else if:
示例代码:
语法格式:
另外,添加 fallthrough 会强制执行后面的 case 语句,不管下一条case语句是否为true。
示例代码:
执行结果:
下面介绍几种循环语句:
执行结果:
执行结果:
也可以通过标记退出循环:
--THE END--
本教程介绍 Go 中多模块工作区的基础知识。使用多模块工作区,您可以告诉 Go 命令您正在同时在多个模块中编写代码,并轻松地在这些模块中构建和运行代码。
在本教程中,您将在共享的多模块工作区中创建两个模块,对这些模块进行更改,并在构建中查看这些更改的结果。
本教程需要 go1.18 或更高版本。使用go.dev/dl中的链接确保您已在 Go 1.18 或更高版本中安装了 Go 。
首先,为您要编写的代码创建一个模块。
1、打开命令提示符并切换到您的主目录。
在 Linux 或 Mac 上:
在 Windows 上:
2、在命令提示符下,为您的代码创建一个名为工作区的目录。
3、初始化模块
我们的示例将创建一个hello依赖于 golang.org/x/example 模块的新模块。
创建你好模块:
使用 . 添加对 golang.org/x/example 模块的依赖项go get。
在 hello 目录下创建 hello.go,内容如下:
现在,运行 hello 程序:
在这一步中,我们将创建一个go.work文件来指定模块的工作区。
在workspace目录中,运行:
该go work init命令告诉为包含目录中模块的工作空间go创建一个文件 。go.work./hello
该go命令生成一个go.work如下所示的文件:
该go.work文件的语法与go.mod相同。
该go指令告诉 Go 应该使用哪个版本的 Go 来解释文件。它类似于文件中的go指令go.mod 。
该use指令告诉 Go在进行构建时hello目录中的模块应该是主模块。
所以在模块的任何子目录中workspace都会被激活。
2、运行工作区目录下的程序
在workspace目录中,运行:
Go 命令包括工作区中的所有模块作为主模块。这允许我们在模块中引用一个包,即使在模块之外。在模块或工作区之外运行go run命令会导致错误,因为该go命令不知道要使用哪些模块。
接下来,我们将golang.org/x/example模块的本地副本添加到工作区。然后,我们将向stringutil包中添加一个新函数,我们可以使用它来代替Reverse.
在这一步中,我们将下载包含该模块的 Git 存储库的副本golang.org/x/example,将其添加到工作区,然后向其中添加一个我们将从 hello 程序中使用的新函数。
1、克隆存储库
在工作区目录中,运行git命令来克隆存储库:
2、将模块添加到工作区
该go work use命令将一个新模块添加到 go.work 文件中。它现在看起来像这样:
该模块现在包括example.com/hello模块和 `golang.org/x/example 模块。
这将允许我们使用我们将在模块副本中编写的新代码,而不是使用命令stringutil下载的模块缓存中的模块版本。
3、添加新功能。
我们将向golang.org/x/example/stringutil包中添加一个新函数以将字符串大写。
将新文件夹添加到workspace/example/stringutil包含以下内容的目录:
4、修改hello程序以使用该功能。
修改workspace/hello/hello.go的内容以包含以下内容:
从工作区目录,运行
Go 命令在go.work文件指定的hello目录中查找命令行中指定的example.com/hello模块 ,同样使用go.work文件解析导入golang.org/x/example。
go.work可以用来代替添加replace 指令以跨多个模块工作。
由于这两个模块在同一个工作区中,因此很容易在一个模块中进行更改并在另一个模块中使用它。
现在,要正确发布这些模块,我们需要发布golang.org/x/example 模块,例如在v0.1.0. 这通常通过在模块的版本控制存储库上标记提交来完成。发布完成后,我们可以增加对 golang.org/x/example模块的要求hello/go.mod:
这样,该go命令可以正确解析工作区之外的模块。