Go语言学习笔记之一
前言
本来是打算学习C++的,用来开发web服务器后端,但是在学习过程中,发现对于新手有点难,内存管理什么的,巴拉巴拉,然后目标盯上了Rust语言,正准备学习的时候,群友推荐我尝试尝试Go语言,在尝试了Go之后确实被吸引了,打算了解了解,在此记录一下自己的学习之路。
HelloWorld
任何语言的第一个程序都应该是hello world(应该);
Go语言的hello world如下:
1 | package main |
执行代码后的输出结果:
基础语法
接下来对这段代码进行一个剖析;
首先第一行 package main
,Go程序是通过包也就是package来组织的,这段代码说明当前的go文件是属于哪个包,在这个例子中包名为 main
,也就意味着这是一个独立的包,在执行编译之后会生成一个可执行文件;
如果要在该主程序中引入其他的go文件,也就是其他的包,那么只有该 main
主包会生成可执行文件,其他的引入的go文件编译之后只会产生 *.a
文件(也就是包文件);
需要注意的是,每个Go程序必须包含一个
main
主包(有且只有一个),在这个主包内,且必须含有一个main
主函数(有且只有一个)入口,该主函数无参数,无返回值。
第二行 import "fmt"
,和其他编译类语言一样,对于C++或者C语言来说,需要 #include <libName>
,对于Go程序来说,也是需要引入“库”(Go语言中叫“包”),很多的标准函数都是可以通过引入标准包(也就是系统包)来进行调用的。示例这个程序需要进行打印信息,需要调用 Println()
函数,所以需要引入系统包 fmt
。
第三行 func main() { }
,这一行是通过关键字 func
定义了一个 main()
函数,函数体(也就是函数的具体内容)被放在了 { }
大括号中。
第四行 fmt.Println("Hello World!")
,调用了 fmt
包中定义的函数 Println()
,需要输出的内容被引号包裹;对于第五行的代码,它和本行的代码时相似的,Println()
函数代替了 Printf("\n")
可以直接在信息被打印之后进行自动换行,不需要手动去敲换行符,这两个函数可以根据需要去选择调用。
可以看到,Go程序的函数调用,是通过
<packageName>.<functionName>
的方式进行调用的,类似于C++语言中的namespace
命名空间,在某些情况下可以不声明package名的,但是推荐进行声明,避免函数同名冲突。
第五行,在Go程序内部的单行注释,是以 //
开头的,多行注释的结构是 /* */
这样的。同时可以看到,输出的内容里面包含了很多非 ASCII 码字符,Go程序是天生支持UTF-8的,任何字符都可以直接输出,甚至可以用UTF-8中的任何字符作为标识符。
需要非常注意的是,在Go语言中一行代表一个语句的结束,并不需要类似于 ;
这样的分号来分行,Go语言编辑器会自动完成;当然也不是强制性的要求,可以将多行写在一起,用分号隔开:
1 | fmt.Println("Hello!") |
所以在上述HelloWorld的例子中,func main()
是不能和 {
在不同行中的,这必将会引起错误,示例如下:
1 | func main() { |
这一点非常要注意,一不小心就会写错!
标识符用来命名变量、函数等程序实体,例如hello world例子中,main
和 Println
都是标识符。
一个标识符实际上就是一个或是多个字母 A~Z
和 a~z
,数字 0~9
以及下划线 _
组成的序列;
需要注意的是,第一个字符必须是字母或下划线,不能是数字!
标识符的命名,非常推荐使用标准驼峰格式,例如 aaaBbbCcc
,不推荐使用大驼峰格式 AaaBbbCcc
,因为在Go语言中,与JavaScript中的 export
语法一样,如果变量名称以大写字母开头,则Go会导出变量,可以在外部被访问到,例如示例中 fmt.Println()
的 Println
就是 fmt
包中的函数,首字母就是大写的,可以通过引入包来让外部程序访问到该包内的函数/变量等。
所有其他不以大写字母开头的变量对程序包来说都是私有的
Go语言中的保留关键字,也就是不能拿来作为变量/函数的命名:
1 | break default func interface select case defer go map struct chan else goto |
同时还有部分预定义标识符:
1 | append bool byte cap close complex complex64 complex128 uint16 copy false |
对于字符串的简单拼接,可以直接使用 +
即可,例如:
1 | fmt.Println("Hello" + "World!") |
输出:
格式化字符串:
Sprintf()
根据格式化参数生成格式化的字符串并返回该字符串。Printf()
根据格式化参数生成格式化的字符串并输出。
举例:
1 | package main |
输出:
stockcode
传入 url
中的 %d
,enddate
传入 url
中的 %s
,最后将新字符串赋值给 target_url
;在go程序中只能通过 Sprintf()
来格式化字符串,再举个例子:
1 | package main |
输出:
这是 Printf()
的用法,且只能用 Printf()
,如果用 Println()
的话是如下的输出:
可以看到字符串并没有被正确的加载。
定义变量
对于Go语言,定义变量使用的是常见的关键字 var
,但和C++不同的是,Go语言会将变量类型放在变量名后,例如:
1 | // 定义了一个名字叫number,类型为int的变量 |
当然,这是标准的变量定义和赋值方式,go语言里为了方便可以进行简化,例如:
1 | var num1, num2, num3 int = 1, 2, 3 |
在最终的变量定义语句中,可以看到 :=
代替了 var
和 int
的作用,可以直接对变量进行定义,但是该种方法只能用在函数内部,在函数外部还是需要使用 var
关键字。
特殊的变量名:下划线 _
,当下划线作为一个变量名的时候,表示对其赋的值进行丢弃,相当于说是个垃圾场,但不可回收,举个例子,现在有一串数字 1, 2, 3
我只需要收到 2
和 3
,那么可以这样写:
1 | _, num1, num2 = 1, 2, 3 |
1
的值赋给了下划线,表示被丢弃,2
的值赋给了 num1
,3
的值赋给了 num2
。
Go语言中的变量,就和喜欢的姑娘一样,请务必负责到底,如果你和她在一起了(定义了这个变量),却没有负责到底(使用这个变量),那么就会挨打(编译器会报错)!例如:
1 | func main() { |
输出:
注意,在上述例子中,我们为什么要多此一举去写一句
fmt.Println("Hello!")
,因为和变量一样,如果我们引用了fmt
这个包,但是没有去使用这个包,编译器同样也会报错!
鸽子
临时被安排了其他开发任务,要开始主攻 C++/CAPE-OPEN
方向了,Go语言的学习先暂告一段落~