17. go语言快速入门

一、go语言介绍

go全称为 Golang,是开源的编程语言,它能让构造简单、可靠且高效的软件变得非常容易。

使用过C/C++里面线程的我们应该都知道,其使用起来非常的麻烦,不仅调用麻烦,如果想要同步数据就还需要各种锁,并且一个线程需要占用数兆内存。

go中有专门的goroutine (轻量级线程实现)解决了这个问题,一个goroutine 仅占数K内存大小,并且其有专门的channel作为goroutine之间的数据传输结构,完全没有锁的概念,使用起来更加简单。

也正是由于这个极好的特性,go语言在服务器上使用的较多。

而且最重要的是,它的语法非常简单,接近JavaScript,并且其生成的可执行文件运行效率接近C++,不仅跨平台,它还有大量的库可以让我们直接使用。

也正由于这个特性,如果有时我们想要节约开发成本,又想要写一个高效率的程序或脚本,那就可以使用go语言(python语言开发虽然快,但执行效率相比较而言真的很低)。

二、go开发环境配置

首先点击这里,去go语言官网下载go安装包:

image.png

然后选择自己合适的版本:

image.png

因为我用的windows,所以就下载的windows版本。

下载完成后,一路点击安装即可,然后打开控制台,输入go:

image.png

有输出信息则安装成功

前面说了,go语言有很多库可以让我们使用,但由于其默认的库都在外网,所以有时候下载起来会很慢(或者根本下载不了)

这时我们就可以调整一下go的默认配置,设置国内代理,打开控制台输入:

go env -w GOPROXY=https://goproxy.cn,direct

这样我们的go语言开发环境就配置好了。

但如果用记事本码代码,有点过于原始,所以一般我们还是要下载个专业的编辑器,比如vscode,点击这里跳转。

然后你可以在桌面或任意文件夹中,新建一个go文件夹,里面新建一个main.go的文件(当然你也可以任意取其它名字,但.go后缀不要动)。

image.png

然后,在控制台中进入这个文件夹(cd命令,或者直接在该文件夹上面的文件路径中输入cmd,然后Enter

然后输入:code .

image.png

这是vscode的命令,.代表当前目录,即用vscode打开当前目录。

打开main.go文件,这时vscode就会在软件的右下角提醒你安装所有需要的插件,全部点安装即可。

三、Go语言组织结构

先将下面这段代码复制进main.go文件中:

package main

import "fmt"

func main() {
	fmt.Println("Hello world")
}

这时vscode大概长下面这样:

image.png

这就是一段输出Hello World字符串的代码而已。

Ctrl+S保存后,在控制台中进入这个目录,输入 go run main.go

image.png

是不是非常简单!

现在我们就来理一理上面这些步骤都是在干嘛,有什么作用。

  • 首先是代码中第一行的package main

C/C++不同,go语言采用包的概念组织代码(一个包相当于C++中的一个库,类似于vector),并且我们的主函数所在的程序必须在main包里面(这是go语言的规定),这个main.go文件为我们的主函数main函数所在的文件,因此需要在最前面申明该文件中的代码为main包中的

  • 然后是第二行代码import "fmt"

既然有申明包,那肯定就有导入包,该行代码的意思就是导入fmt包。我们将要使用该包中的东西(fmt为官方标准库,为format的缩写,即格式化库,常用于输出输入)

  • 第三行代码:func main()

这也是与C/C++的不同之处,即申明一个函数只需要在函数名前面添加func关键字即可,而main是必须要的函数名称,为程序的执行入口,这一点和C/C++相同。

  • 第四行代码:fmt.Println("Hello world")

这就是在调用fmt这个包中的Println函数,进行打印字符串,安装好vscode相关go的插件后,当你输入fmt.,就会自动提示其拥有的函数

  • 控制台命令: go run main.go

go即为前面我们安装好的go语言安装包中的软件,run代表运行,main.go则为要运行的文件

但每次运行都需要用源代码也着实有些麻烦了,可不可以只编译呢?

当然也是可以的!将go run main.go改为下面这个命令即可

go build main.go

事实上,run命令也是间接调用了build命令,然后执行的,即先编译,再执行。

这时你就可以在代码目录中看到编译生成的可执行文件了!

为了更加切身体验,所以下面我们来找找上面提到的软件与包,控制台中输入go env,会列出go的各种环境变量:

image.png

我们主要需要关注的是上面两个变量值,为两个本地路径。

首先来到GOROOT变量的路径下,在bin目录中我们就可以看到两个程序:

image.png

  • go.exe:即编译运行源代码的程序,上面我们已经用过了
  • gofmt.exe:格式化代码格式的软件

go与C++不同,它有标准的代码格式,即无论你将代码写成什么样,为源代码运行这个gofmt.exe程序,就会成为标准格式的代码。

而在vscode中,只要你按Ctrl+S进行保存,vscode就会自动为你调用这个程序,使其成为标准格式的代码,因此这个程序我们无需操心

然后是src目录中:

image.png

就可以看到go的标准库源代码,上面我们使用到的fmt也在其中。

注意,go共享代码不是像C/C++那样提供静态库或动态库,而是直接提供源代码,一个文件夹就代表go中的一个包,包里面的就是源代码。

然后来到GOPATH目录:

image.png

这个目录里面的东西就是用户自己下载的程序或包,比如bin目录中:

image.png

这里有两个exe程序,它们是当你第一次使用vscode打开go代码时,提示你安装的。

  • gopls.exe:提供了很多 IDE 才有的功能,例如自动补全、重构、工作空间符号搜索、代码美化和诊断分析任何兼容的编辑器前端
  • staticcheck.exe:看名字就知道,是静态检测代码的。

这些都不用我们管,然后来到pkg目录中:

image.png

首先是两个文件夹:

  • mod:存放我们下载的第三方库
  • sumdb:记录使用的第三方库相关信息

四、go语法速览

1.基础

相比于C/C++,go的语法很少。

首先是数据类型,常用的有boolintfloat32string,更多类型可以点击这里查看。

有了数据类型,接下来就是声明变量,主要有以下几种方式:

	var age int //只声明
	var (       //同时声明多个,可以这样简写
		name  string
		name1 string
	)

	var age1 int = 10 //声明的同时进行初始化赋值
	var (             //声明并赋值多个
		name2 string = "www.kucoding.com"
		name3 string = "yushi-"
	)

	var age2 = 20 //go可自动推断数据类型,因此可不写int,因为根据20可推断出其为int类型

	var ( //声明并赋值多个,可省略类型
		name4 = "www.kucoding.com"
		name5 = "yushi-"
	)

	age3 := 30 //在声明的同时赋值,则可以用 := 代替 = ,这样就可以不写var关键字

注意其与C/C++的区别,声明变量需要添加关键字var,并且类型写在变量名的后面。

虽然看上去也挺多的,但事实上我们使用的最多的应该就是最后一种:age3:=30,这样一看,是不是就简单多了呢?

同时注意go中每条语句后面不需要添加;,即使你添加了,gofmt.exe也会给你删掉(vscode中保存代码时,会自动调用)。

还有就是,如果你复制了上面的代码到自己的程序中,可能就会看见报错:

image.png

这也是go的特色,不允许你声明不使用的变量,只要你在最后调用一下 fmt.Println就不会报错了:

image.png

小技巧:对于导入库的操作(如import “fmt”),你无需亲手操作,只要你在代码中使用到了fmt,保存一下源码,就会自动为你添加(同时没有使用到的库,也会自动为你去除)

有变量就有常量,只需要将前面声明变量的关键字var改为const即可:

	const age int = 10 //由于是常量,不可更改,因此必须在声明的同时进行赋值
	const age1 = 20    //而go可自动推断数据类型,因此可以简写
	const (            //同时定义多个常量
		num1 = 0
		num2 = 1
		num3 = 2
	)
	const ( //对于有规律的赋值操作,可以使用iota变量,其默认为0,并且每增加一行,就自动加1,该语句与上面的语句等价
		num4 = iota
		num5
		num6
	)

至于运算符,就不多说了,C/C++中有的,go基本都有,可以点击这里查看go中的运算符。

然后是判断语句,与C/C++差不多:

	b := 0
	if b == 0 {
		fmt.Println("b为0")
	} else if b == 1 {
		fmt.Println("b为1")
	} else {
		fmt.Println("b为其它值")
	}

不同点在于,这里的判断语言,无需添加小括号,而且上面的语句还可以进行简化:

	if b := 0; b == 0 {
		fmt.Println("b为0")
	} else if b == 1 {
		fmt.Println("b为1")
	} else {
		fmt.Println("b为其它值")
	}

将需要进行判断的变量写在if中,这样的好处是不污染变量环境,如这里的b变量名只在当前的if语句中有效,后面你可以继续重新声明定义b变量。

然后是switch语句,与C/C++同样类似:

	b := 0
	switch b {
	case 0:
		fmt.Println("b为0")
	case 1:
		fmt.Println("b为1")
	case 2:
		fmt.Println("b为2")
	default:
		fmt.Println("b为其它值")
	}

不同点在于,switch后面同样不需要小括号,并且每个case最后不需要添加break,其默认只执行该case语句,如果你想要让它继续执行后面的case语句,可以添加fallthrough关键字

	switch b := 0; b {
	case 0:
		fmt.Println("b为0")
		fallthrough
	case 1:
		fmt.Println("b为1")
		fallthrough
	case 2:
		fmt.Println("b为2")
	default:
		fmt.Println("b为其它值")
	}

它同样可以将变量声明定义写在内部。

后面不再赘述,如果看到我有这样的写法,说明它就可以这样用。

当添加了fallthrough关键字后,它就会执行当前语句后,继续执行后的语句,比如上面就会执行0,1,2这三条语句

除了上面那种我们熟悉的写法,go还提供了另外一种写法:

	b := 0
	switch {
	case b == 0:
		fmt.Println("b为0")
	case b == 1:
		fmt.Println("b为1")
	case b == 2:
		fmt.Println("b为2")
	default:
		fmt.Println("b为其它值")
	}

不过我感觉这变得更麻烦了……反正这种写法我目前用的不多。

然后来到循环语句:

	for i := 0; i < 10; i++ {
		fmt.Println(i)
	}

基本写法与C/C++差不多,只是没有小括号而已。

go中的forC/C++中的更加强大,因为go中没有while语句,而是直接使用for语句进行代替:

	i := 0
	for i < 10 {
		fmt.Println(i)
		i++
	}

如果想要写死循环,那还可以这样写:

	i := 0
	for{
		fmt.Println(i)
		i++
	}

此时break关键字就派上用场了,即跳出当前循环,还有continue关键字,同样也是可以使用的。

除了这两种基本的写法,它还可以遍历数组:

	nums := []string{"www.kucoding.com", "yushi-"}
	for index, value := range nums {
		fmt.Println(index, value)
	}

可以用range关键字来遍历数组,每次遍历会返回两个值,第一个为下标,第二个为该下标对应的值,上面的运行结果为:

0 www.kucoding.com
1 yushi-

这里说一下go中数组的写法,前面没提到:

	var num []int         //声明变长的数组
	num = append(num, 10) //通过append函数为其添加值,当内存不够时,会自动扩充

	var num1 [3]int //声明指定长度的数组
	num1[0] = 20    //直接通过下标进行赋值

	num3 := []int{1, 2, 3}  //变长数组,初始化并赋值
	num4 := [3]int{1, 2, 3} //定长数组初始化并赋值

	num5 := [3]int{0: 10, 2: 20} //指定位置初始化赋值

	fmt.Println(num)
	fmt.Println(num1)
	fmt.Println(num3)
	fmt.Println(num4)
	fmt.Println(num5)

结果为:

[10]
[20 0 0]
[1 2 3]
[1 2 3]
作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux