新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
相比很多其它流行语言,Go的语法相对简洁。 此篇文章将介绍编程中常用的代码元素,并展示一份简单的Go程序代码,以便让刚开始学Go编程的程序员对Go代码结构有一个大概的印象。
创新互联建站长期为超过千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为钦北企业提供专业的成都网站制作、网站建设、外贸网站建设,钦北网站改版等技术服务。拥有10年丰富建站经验和众多成功案例,为您定制开发。
编程和程序代码元素
简单来讲,编程可以看作是以各种方式控制和组合计算机运行中的各种操作,以达到各种各样的目的。 一个操作可能从一个硬件设备读取、或者向一个硬件设备写入一些数据,从而完成一个特定的任务。 对于现代计算机来说,最基本的操作是底层计算机指令,比如CPU和GPU指令。 常见的硬件设备包括内存、磁盘、网卡、显卡,显示器、键盘和鼠标等。
直接操控底层计算机指令进行编程是非常繁琐和容易出错的。 高级编程语言通过对底层指令进行一些封装和对数据进行一些抽象,从而使得编程变得直观和易于理解。
在流行高级编程语言中,一个操作通常是通过函数(function)调用或者使用操作符(operator)运算来完成的。 大多数高级编程语言都支持一些条件和循环控制语句。 这些条件和循环控制语句可以看作是特殊的操作。 它们的语法接近于人类语言,因此一个人写的代码很容易被其他人理解。
在大多数高级编程语言中,数据通常被抽象为各种类型(type)和值(value)。 一个类型可以看作是值的模板。一个值可以看作是某个类型的实例。 大多数编程语言支持自定义类型和若干预声明类型(即内置类型)。 一门语言的类型系统可以说是这门语言的灵魂。
编程中常常会使用大量的值。 一些在编码阶段可确定的值可以用它们的字面形式(literal,即字面量)来表示。 为了编程灵活和不易出错,其它的值一般使用变量(variable)和(具名)常量(named constant)来表示。
在《Go语言101》中,具名的函数、具名的值(包括变量和具名常量)、以及定义类型和类型别名将被统称为代码要素。 代码要素名必须为标识符(identifier)。
高级编程语言代码将被编译器或者解释器转换为底层机器码进行执行。 为了帮助编译器和解释器解析高级语言代码,一些单词将被用做关键字(keyword)。 这些单词不能被当做标识符使用。
很多现代高级语言使用包(package)来组织代码。 一个包必须引入(import)另一个包才能使用另一个包中的公有(导出的)代码要素。 包名和包的引入名也都必须是标识符。
尽管高级编程语言代码比底层机器指令友好和易懂,我们还是需要一些注释来帮助自己和其他程序员理解我们所写的代码。 在下一节的程序示例中,我们可以看到很多注释。
一个简单的Go示例程序
为了对各种代码元素有一个更清楚的认识,让我们来看一个简短的Go示例程序。 和很多其流行语言一样,Go使用//来起始一个行注释,使用一个/*和*/对来包裹一个块注释。
下面是这个Go示例程序。请注意阅读其中的注释。程序之后有更多解释。
package main // 指定当前源文件所在的包名
import "math/rand" // 引入一个标准库包
const MaxRand = 16 // 声明一个具名整型常量
// 一个函数声明
/*
StatRandomNumbers生成一些不大于MaxRand的非负
随机整数,并统计和返回小于和大于MaxRand/2的随机数
个数。输入参数numRands指定了要生成的随机数的总数。
*/
func StatRandomNumbers(numRands int) (int, int) {
// 声明了两个变量(类型都为int,初始值都为0)
var a, b int
// 一个for循环代码块
for i := 0; i numRands; i++ {
// 一个if-else条件控制代码块
if rand.Intn(MaxRand) MaxRand/2 {
a = a + 1
} else {
b++ // 等价于:b = b + 1
}
}
return a, b // 此函数返回两个结果
}
// main函数,或主函数,是一个程序的入口函数。
func main() {
var num = 100
// 调用上面声明的StatRandomNumbers函数,
// 并将结果赋给使用短声明语句声明的两个变量。
x, y := StatRandomNumbers(num)
// 调用两个内置函数(print和println)。
print("Result: ", x, " + ", y, " = ", num, "? ")
println(x+y == num)
}
将上面的程序代码存盘到一个名为basic-code-element-demo.go 的文件中并使用下列命令运行此程序:
$ go run basic-code-element-demo.go
Result: 46 + 54 = 100? true
在上面的示例程序中,单词package、import、const、func、var、for、if、else和return均为关键字。 其它大多数单词均为标识符。 请阅读关键字和标识符以获得更多关于关键字和标识符的信息。
四个int(一个在第15行,另三个在第13行) 表示内置基本类型int。int类型是Go中的基本整数类型之一。 第5行中的16、第17行中的0、 第20行中的1以及第30行的100均为整型字面量。 第35行的"Result: "是一个字符串字面量。 请阅读基本类型和它们的字面量表示以获取更多关于基本类型和它们的字面量的信息。 Go中的非基本类型(均为组合类型)将在以后的其它文章中介绍和解释。
第20行是一个赋值语句。 第5行声明了一个具名常量,叫做MaxRand。 第15行和第30行使用标准变量声明语句声明了三个变量。 第17行的变量i以及第33行的变量x和y是使用变量短声明语句声明的。 变量a和b在声明的时候被指定为int类型。 编译器会自动推导出变量i、num、x和y的类型均为int类型,因为它们的初始值都是整型字面量表示的。 请阅读常量和变量以获取什么是类型不确定值、类型推导、赋值、以及如何声明变量和具名常量。
上面的示例程序中使用了很多操作符,比如第17和19行的小于比较符,第36行的等于比较符==,还有第20和36行的加法运算符+。 第35行中的+不是一个运算符,它是一个字符串字面量中的一个字符。 一个使用操作符的操作中涉及到的值称为操作值(有时也可称为运算数)。 请阅读常用操作符以获取更多关于操作符的信息。 更多操作符将在后续其它文章中介绍。
第35和36行调用了两个内置函数print和println。 从第13行到第26行声明的函数StatRandomNumbers在第33行被调用。 第19行也调用了一个函数 Intn。 这个函数声明在math/rand标准库包中。 请阅读函数声明及函数调用以获取更多关于函数声明及函数调用的信息。
(注意,一般print和println这两个内置函数并不推荐使用。 在正式的项目中,我们应该尽量使用fmt标准库包中声明的相应函数。 《Go语言101》只在开始的几篇文章中使用了这两个函数。)
第1行指定了当前源文件所处的包的名称。 一个Go程序的主函数(main函数)必须被声明在一个名称为main的包中。 第3行引入了math/rand标准库包,并以rand做为引入名。 在这个包中声明的Intn函数将在第19行被调用。 请阅读代码包和包引入,以获取更多关于代码包和包引入的信息。
表达式、语句和简单语句一文中介绍了什么是表达式和语句。特别地,此文列出了所有的简单语句类型。 在Go代码中,各种流程控制代码块中的某些部分必须为简单语句,某些部分必须为表达式。
StatRandomNumbers函数的声明体中使用了两个流程控制代码块。 其中一个是for循环代码块,它内嵌了另外一个代码块。 另外一个代码块是一个if-else条件控制代码块。 请阅读基本流程控制语法以获取更多关于流程控制代码块的信息。 更多的特殊的流程控制代码块将在以后的其它文章中介绍。
空行常常用来增加代码的可读性。 上面的程序中也包涵了很多注释,但它们大多是为了Go初学者快速理解的目的而加入的。 我们应该尽量使代码自解释,只在确实需要解释的地方进行注释。
关于代码断行
像很多其它流行编程语言一样,Go也使用一对大括号{ and }来形成一个显式代码块。但是在Go代码中,编码样式风格有一些限制。 比如,很多左大括号{不能被放到下一行。 如果,上面的StatRandomNumbers被修改成如下所示,则上面的示例程序将编译不通过。
func StatRandomNumbers(numRands int) (int, int)
{ // 编译错误:语法错误
var a, b int
for i := 0; i numRands; i++
{ // 编译错误:语法错误
if rand.Intn(MaxRand) MaxRand/2
{ // 编译错误:语法错误
a = a + 1
} else {
b++
}
}
return a, b
}
一些程序员不是很喜欢这些限制。但是这些限制有两个好处:
它们使得Go程序编译得非常快。
它们使得不同的Go程序员编写的代码风格类似,从而一个Go程序员写的代码很容易被另一个程序员看懂。
我们可以阅读代码断行规则一文以获取更多关于代码换行规则的细节。在目前,我们最好避免将左大括号放在下一行。 或者说,每行的非空起始字符不能是左大括号(但是,请记住,这不是一个普适的规则
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
当需要定义一个整形变量a 心里是这样想的:我现在需要一个整形的变量,我要定义它,于是我先写一个int,再思考它的名字 a ,于是就这么写出来了int a 。而不是我写了个变量a,我得给它区分个类型int。2. 在调用一个方法的时候,func(abdfsasdffdg int, bagressdgf string, csdgesredg bool) 那个go函数看的很乱,程序员其实根本就不怎么看参数名字是什么,而只是看需要传入什么类型,注意力只在于int,string,bool这三个,如果如上那么写,反而影响了视线,乱系八糟的。func(int adsfasdfsdaf, string asdfasfasf, bool gwegasgs),这么写我只注意类型,就不受名称影响了。3. IDE自动提示 go本身就是为快而生,定义一个结构变量Rectangle rectangle,当键盘敲下r时候,IDE会自动给出rectangle,直接回车就出来了,反过来就的自己一个字母一个字母敲上去,蛋疼啊4. 至于go给出的解释,当遇到复杂函数时…… 一个项目中能写几个复杂函数,为了去解决这么一点小问题就把优势给牺牲了.