十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
【格式化输出】
我们提供的服务有:成都网站建设、网站建设、微信公众号开发、网站优化、网站认证、颍州ssl等。为上千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的颍州网站制作公司
// 格式化输出:将 arg 列表中的 arg 转换为字符串输出
// 使用动词 v 格式化 arg 列表,非字符串元素之间添加空格
Print(arg列表)
// 使用动词 v 格式化 arg 列表,所有元素之间添加空格,结尾添加换行符
Println(arg列表)
// 使用格式字符串格式化 arg 列表
Printf(格式字符串, arg列表)
// Print 类函数会返回已处理的 arg 数量和遇到的错误信息。
【格式字符串】
格式字符串由普通字符和占位符组成,例如:
"abc%+ #8.3[3]vdef"
其中 abc 和 def 是普通字符,其它部分是占位符,占位符以 % 开头(注:%% 将被转义为一个普通的 % 符号,这个不算开头),以动词结尾,格式如下:
%[旗标][宽度][.精度][arg索引]动词
方括号中的内容可以省略。
【旗标】
旗标有以下几种:
空格:对于数值类型的正数,保留一个空白的符号位(其它用法在动词部分说明)。
0 :用 0 进行宽度填充而不用空格,对于数值类型,符号将被移到所有 0 的前面。
其中 "0" 和 "-" 不能同时使用,优先使用 "-" 而忽略 "0"。
【宽度和精度】
“宽度”和“精度”都可以写成以下三种形式:
数值 | * | arg索引*
其中“数值”表示使用指定的数值作为宽度值或精度值,“ ”表示使用当前正在处理的 arg 的值作为宽度值或精度值,如果这样的话,要格式化的 arg 将自动跳转到下一个。“arg索引 ”表示使用指定 arg 的值作为宽度值或精度值,如果这样的话,要格式化的 arg 将自动跳转到指定 arg 的下一个。
宽度值:用于设置最小宽度。
精度值:对于浮点型,用于控制小数位数,对于字符串或字节数组,用于控制字符数量(不是字节数量)。
对于浮点型而言,动词 g/G 的精度值比较特殊,在适当的情况下,g/G 会设置总有效数字,而不是小数位数。
【arg 索引】
“arg索引”由中括号和 arg 序号组成(就像上面示例中的 [3]),用于指定当前要处理的 arg 的序号,序号从 1 开始:
'[' + arg序号 + ']'
【动词】
“动词”不能省略,不同的数据类型支持的动词不一样。
[通用动词]
v:默认格式,不同类型的默认格式如下:
布尔型:t
整 型:d
浮点型:g
复数型:g
字符串:s
通 道:p
指 针:p
无符号整型:x
T:输出 arg 的类型而不是值(使用 Go 语法格式)。
[布尔型]
t:输出 true 或 false 字符串。
[整型]
b/o/d:输出 2/8/10 进制格式
x/X :输出 16 进制格式(小写/大写)
c :输出数值所表示的 Unicode 字符
q :输出数值所表示的 Unicode 字符(带单引号)。对于无法显示的字符,将输出其转义字符。
U :输出 Unicode 码点(例如 U+1234,等同于字符串 "U+%04X" 的显示结果)
对于 o/x/X:
如果使用 "#" 旗标,则会添加前导 0 或 0x。
对于 U:
如果使用 "#" 旗标,则会在 Unicode 码点后面添加相应的 '字符'(前提是该字符必须可显示)
[浮点型和复数型]
b :科学计数法(以 2 为底)
e/E:科学计数法(以 10 为底,小写 e/大写 E)
f/F:普通小数格式(两者无区别)
g/G:大指数(指数 = 6)使用 %e/%E,其它情况使用 %f/%F
[字符串或字节切片]
s :普通字符串
q :双引号引起来的 Go 语法字符串
x/X:十六进制编码(小写/大写,以字节为元素进行编码,而不是字符)
对于 q:
如果使用了 "+" 旗标,则将所有非 ASCII 字符都进行转义处理。
如果使用了 "#" 旗标,则输出反引号引起来的字符串(前提是
字符串中不包含任何制表符以外的控制字符,否则忽略 # 旗标)
对于 x/X:
如果使用了 " " 旗标,则在每个元素之间添加空格。
如果使用了 "#" 旗标,则在十六进制格式之前添加 0x 前缀。
[指针类型]
p :带 0x 前缀的十六进制地址值。
[符合类型]
复合类型将使用不同的格式输出,格式如下:
结 构 体:{字段1 字段2 ...}
数组或切片:[元素0 元素1 ...]
映 射:map[键1:值1 键2:值2 ...]
指向符合元素的指针:{}, [], map[]
复合类型本身没有动词,动词将应用到复合类型的元素上。
结构体可以使用 "+v" 同时输出字段名。
【注意】
1、如果 arg 是一个反射值,则该 arg 将被它所持有的具体值所取代。
2、如果 arg 实现了 Formatter 接口,将调用它的 Format 方法完成格式化。
3、如果 v 动词使用了 # 旗标(%#v),并且 arg 实现了 GoStringer 接口,将调用它的 GoString 方法完成格式化。
如果格式化操作指定了字符串相关的动词(比如 %s、%q、%v、%x、%X),接下来的两条规则将适用:
4。如果 arg 实现了 error 接口,将调用它的 Error 方法完成格式化。
5。如果 arg 实现了 string 接口,将调用它的 String 方法完成格式化。
在实现格式化相关接口的时候,要避免无限递归的情况,比如:
type X string
func (x X) String() string {
return Sprintf("%s", x)
}
在格式化之前,要先转换数据类型,这样就可以避免无限递归:
func (x X) String() string {
return Sprintf("%s", string(x))
}
无限递归也可能发生在自引用数据类型上面,比如一个切片的元素引用了切片自身。这种情况比较罕见,比如:
a := make([]interface{}, 1)
a[0] = a
fmt.Println(a)
【格式化输入】
// 格式化输入:从输入端读取字符串(以空白分隔的值的序列),
// 并解析为具体的值存入相应的 arg 中,arg 必须是变量地址。
// 字符串中的连续空白视为单个空白,换行符根据不同情况处理。
// \r\n 被当做 \n 处理。
// 以动词 v 解析字符串,换行视为空白
Scan(arg列表)
// 以动词 v 解析字符串,换行结束解析
Scanln(arg列表)
// 根据格式字符串中指定的格式解析字符串
// 格式字符串中的换行符必须和输入端的换行符相匹配。
Scanf(格式字符串, arg列表)
// Scan 类函数会返回已处理的 arg 数量和遇到的错误信息。
【格式字符串】
格式字符串类似于 Printf 中的格式字符串,但下面的动词和旗标例外:
p :无效
T :无效
e/E/f/F/g/G:功能相同,都是扫描浮点数或复数
s/v :对字符串而言,扫描一个被空白分隔的子串
对于整型 arg 而言,v 动词可以扫描带有前导 0 或 0x 的八进制或十六进制数值。
宽度被用来指定最大扫描宽度(不会跨越空格),精度不被支持。
如果 arg 实现了 Scanner 接口,将调用它的 Scan 方法扫描相应数据。只有基础类型和实现了 Scanner 接口的类型可以使用 Scan 类方法进行扫描。
【注意】
连续调用 FScan 可能会丢失数据,因为 FScan 中使用了 UnreadRune 对读取的数据进行撤销,而参数 io.Reader 只有 Read 方法,不支持撤销。比如:
go语言中的if语句和其他语言中的类似,都是根据给定的条件表达式运算结果来,判断执行流程。
注意:在go语言中 布尔表达式不用使用括号。
根据布尔值flag判断
程序运行结果
初始变量可以声明在布尔表达式里面,注意它的作用域
程序运行结果
注意:不能使用0或非0表示真假
go语言if语句使用提示:
go语言中的if else语句可以根据给定条件二选一。
比较两个数的大小
运行结果
判断一个数是奇数还是偶数
运行结果
判断一个人是否成年
运行结果
特殊写法,在if前面添加执行语句
运行结果
go语言if语句使用提示:
go语言if语句可以进行多重嵌套使用,进行多重判断。
根据分数判断等级
运行结果
同样也可以写成这样
运行结果
输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续判断第二个字母
运行结果
go语言if语句可以嵌套多级进行判断。
判断三个数的大小
运行结果
判断男生还是女生,还有是否成年
运行结果
1,go的变量声明顺序是:”先写变量名,再写类型名“,此与C/C++的语法孰优孰劣,可见下文解释:
2,go是通过package来组织的(与python类似),只有package名为main的包可以包含main函数,一个可执行程序有且仅有一个main包,通过import关键字来导入其他非main包。
3,可见性规则。go语言中,使用大小写来决定该常量、变量、类型、接口、结构或函数是否可以被外部包含调用。根据约定,函数名首字母小写即为private,函数名首字母大写即为public。
4,go内置关键字(25个均为小写)。
5,函数不用先声明,即可使用。
6,在函数内部可以通过 := 隐士定义变量。(函数外必须显示使用var定义变量)
7,go程序使用UTF-8编码的纯Unicode文本编写。
8,使用big.Int的陷阱:
9,从技术层面讲,go语言的语句是以分号分隔的,但这些是由编译器自动添加的,不用手动输入,除非需要在同一行中写入多个语句。没有分号及只需少量的逗号和圆括号,使得go语言的程序更容易阅读。
10,go语言只有一个循环结构——for循环。
11,go里的自增运算符只有——“后++”
12,go语言中的slice用法类似python中数组,关于slice的详细用法可见:
13,函数也是一个值,使用匿名函数返回一个值。
14,函数闭包的使用,闭包是一个匿名函数值,会引用到其外部的变量。
GO是编译性语言,所以函数的顺序是无关紧要的,为了方便阅读,建议入口函数 main 写在最前面,其余函数按照功能需要进行排列
GO的函数 不支持嵌套,重载和默认参数
GO的函数 支持 无需声明变量,可变长度,多返回值,匿名,闭包等
GO的函数用 func 来声明,且左大括号 { 不能另起一行
一个简单的示例:
输出为:
参数:可以传0个或多个值来供自己用
返回:通过用 return 来进行返回
输出为:
上面就是一个典型的多参数传递与多返回值
对例子的说明:
按值传递:是对某个变量进行复制,不能更改原变量的值
引用传递:相当于按指针传递,可以同时改变原来的值,并且消耗的内存会更少,只有4或8个字节的消耗
在上例中,返回值 (d int, e int, f int) { 是进行了命名,如果不想命名可以写成 (int,int,int){ ,返回的结果都是一样的,但要注意:
当返回了多个值,我们某些变量不想要,或实际用不到,我们可以使用 _ 来补位,例如上例的返回我们可以写成 d,_,f := test(a,b,c) ,我们不想要中间的返回值,可以以这种形式来舍弃掉
在参数后面以 变量 ... type 这种形式的,我们就要以判断出这是一个可变长度的参数
输出为:
在上例中, strs ...string 中, strs 的实际值是b,c,d,e,这就是一个最简单的传递可变长度的参数的例子,更多一些演变的形式,都非常类似
在GO中 defer 关键字非常重要,相当于面相对像中的析构函数,也就是在某个函数执行完成后,GO会自动这个;
如果在多层循环中函数里,都定义了 defer ,那么它的执行顺序是先进后出;
当某个函数出现严重错误时, defer 也会被调用
输出为
这是一个最简单的测试了,当然还有更复杂的调用,比如调试程序时,判断是哪个函数出了问题,完全可以根据 defer 打印出来的内容来进行判断,非常快速,这种留给你们去实现
一个函数在函数体内自己调用自己我们称之为递归函数,在做递归调用时,经常会将内存给占满,这是非常要注意的,常用的比如,快速排序就是用的递归调用
本篇重点介绍了GO函数(func)的声明与使用,下一篇将介绍GO的结构 struct
Python是什么呢?Python是一个功能强大的高级编程语言,主要用于科学和工程计算,是一种高效的编程语言,布局简洁而强大,适合新手以及专业人士学习。
Go是什么呢?Go是一种通用编程语言,由Google设计,借鉴了许多其他有好主意的语言,同时也避免了会导致的复杂性和不可靠代码的功能。
那两者的区别是什么?
从范例上来讲:Python是一种基于面向对象编程的多范式,命令式和函数式编程语言。Go是一种基于并发编程范式的过程编程语言,它与C具有表面相似性。
从类型化上来讲:Python是动态类型语言,GO语言是静态类型化语言,实际有助于编译捕获错误,可以减少生产后期的错误。
从并发上来讲:Python没有提供内置的并发机制,而Go有内置的并发机制。
从安全性上来讲:Python是强类型语言,通过编译的,增加了安全性;而GO具有分配给每个变量的类型,因此它提供了安全性。
从速度上来讲:GO语言的速度要比Python快。
从用法上来讲:Python更多地用于Web应用程序,它非常适合解决数据科学问题。Go更多地围绕系统编程,即Go更像是一种系统语言。
从管理内存上来讲:Go允许程序员在很大程度上管理内存;而python语言内存管理完全自动化并由python VM管理,不允许程序员对内存管理负责。
从库上来讲:对比GO语言,python提供的库数量要大得多。
从语法上来讲:Python的语法使用缩进来指示代码块。Go的语法基于打开和关闭括号。
从详细程度上来讲:想要获得同样功能,Golang代码通常需要编写比Python代码更多的字符。
本教程介绍了 Go 中模糊测试的基础知识。通过模糊测试,随机数据会针对您的测试运行,以尝试找出漏洞或导致崩溃的输入。可以通过模糊测试发现的一些漏洞示例包括 SQL 注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。
在本教程中,您将为一个简单的函数编写一个模糊测试,运行 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; 新的失败种子语料库条目将被使用:
由于我们的测试失败,是时候调试了。