Go语言官网:https://golang.org/
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.
Go是一种开源编程语言,它使构建简单、可靠和高效的软件变得容易。
上面是官网对Go语言的描述。官网里的“hello world”。
看起来,好像和其它语言也差不多的结构。
学新的编程语言,我们第一时间把环境安装好。
我们先在自己的个人电脑安装,我自己是WIN10系统,先到官网下载一个安装包。
下的是当前最新的版本“go1.17.2.windows-amd64.msi”。
下载好后,双击打开:
点击“Next”:
选择合适的路径:
稍微等一会:
最后“Finish”:
接下来,我们验证一下,是否已经安装成功。
找个目录,新建一个文本文件,命名为:HelloWorld.go。
然后在“HelloWorld.go”输入以下代码:
package mainimport "fmt"func main() { fmt.Println("Hello World")}
就是最简单的“Hello World”代码。
在“HelloWorld.go”当前目录,打开命令控制台,执行以下命令:
go run HelloWorld.go
如图:
因此,我们的Go环境,是已经安装好。
另外,如果大家在控制台不能直接执行“go”命令,则有可能没有配置环境变量。但我自己发现一个现象,好像win10后,安装java或者python的时候,都会自动添加到环境变量,不需要自己配置,我自己这次安装go环境也是,都是直接帮我添加好环境变量。
如果没有添加,则需要我们自己手动添加,大致如下:
新建系统环境变量:
起个变量名,变量值为Go环境的安装目录:
最后修改系统变量的path,如下:
因为我自己已经有Java开发语言的基础,根据经验,不同的编程语言,基础语法会有所不同,但应该都是大同小异。所以,就没必要向零基础那样学习方式,先大概了解一下所有内容,后续我们再根据实际情况来加深学习。
为了更好的使用Go语言,我们还是需要先安装好开发工具,提高我们的编码效率。
首先试一下这个开源的工具,官网地址:https://sourceforge.net/projects/liteide/
下载回来之后,直接解压就可以使用。
找到上面这个执行文件,直接双击打开就可以使用。
在使用过程中,需要注意的一些细节。
第一:这里要选择自己系统的版本。
第二:如果执行的时候,报以下错误:
go: cannot find GOROOT directory: c:\go
则需要配置运行环境。从这里点击打开。
把这里修改成你自己的Go环境的安装路径:
第三:如果在运行的过程中,报以下错误:
go: cannot find main module, but found .git/config in....
则可按照以下方法来解决:
在自己的命令控制台,执行以下命令:
go env -w GO111MODULE=off
GoLand 是 Jetbrains 家族的 Go 语言 IDE,Jetbrains产品的口碑,一直都是挺好的,就是收费贵而已,安装那些流程就免了。
那我们在GoLand写一个“Hello World"试一下,看看是什么效果。
新建一个projec:
配置路径:
新建一个go file的空文件:
编写最简单的“Hello World”代码:
package TestGoLand01import "fmt"func main() { fmt.Println("Hello World")}
然后,运行看看效果:
弹出以上窗口,先不管它,直接继续”Run“。
Error running 'go build TestGoLand.go': Cannot run program "C:\Users\ispea\AppData\Local\Temp\GoLand\___1go_build_TestGoLand_go.exe" (in directory "E:\ispeasant\github\bwzydy4learn\Go\TestGoLand01"): CreateProcess error=216, 该版本的 %1 与你运行的 Windows 版本不兼容。请查看计算机的系统信息,然后联系软件发布者。
百度一番之后,说这里出了问题。
按照网上的操作,改成以下情况:
package mainimport "fmt"func main() { fmt.Println("Hello World")}
然后再运行:
Goland的安装好像成功了,后续在学习过程中,再深入研究。
因为我自己是有其它编程语言的基础,为了更加快速学习,我这里记录我自己觉得稍微值得关注的知识点。
Hello World例子:
package mainimport "fmt"func main() { fmt.Println("Hello World")}
“package main”定义了包名,必须在第一行指明这个文件属于哪个包,“package main”表示一个可独立执行的程序,而且每个Go应用程序都包含一个名为“main”的包,这类似程序的入口。
Go语言的“{”是不能单独一行的,不然会报以下错误:
# command-line-arguments.\Demo1.go:5:6: missing function body.\Demo1.go:6:1: syntax error: unexpected semicolon or newline before {
这个确实和Java语言这些不一样,当然只要我们用的是集成开发工具,都会自动辅助生成代码,一般也不会范这些错误。
像GoLand软件,我们可以直接用格式化代码快捷键“Ctrl+Alt+L”,就会帮我们直接格式化代码。
iota,是go语言里的常量计数器,只能在常量的表达式里使用。
iota在const关键字出现时将被重置为0(const内部的第一行之前),const中每新增一行常量声明将使iota计数一次。
iota可以理解为const语句块中的行索引。
使用方式如下:
const( a = iota b = iota c = iota d = iota)fmt.Println(a,b,c,d)
执行结果为:
0 1 2 3
当然,大家也可以采用简化形式:
const( a1 = iota b1 c1 d1)fmt.Println(a1,b1,c1,d1)
执行结果为:
0 1 2 3
如果常量里有其它数据类型,会是什么情况?
const( a2 = iota b2 c2 d2 e2 = "e2" f2 g2)fmt.Println(a2,b2,c2,d2,e2,f2,g2)
其中e2为字符串类型,并赋值,那我们执行看看是什么现象。
0 1 2 3 e2 e2 e2
可以看到,f2和g2并不会继续自增。
那如果是下面这样呢?
const( a3 = iota b3 c3 d3 e3 = "e3" f3 = iota g3)fmt.Println(a3,b3,c3,d3,e3,f3,g3)
我们把f3重新设置为iota。
执行结果如下:
0 1 2 3 e3 5 6
可以看到,f3和g3会重新自增,而且和他们当前行的索引是一致。
=是赋值,:=是声明变量并赋值。:=这个对于我们Java开发工程师来说,一开始可能会有点不习惯,但对于Go语言来说,它确实挺方便的。
:=是通过系统自动推断类型,不需要var关键字,可以简化我们代码,当然可能会影响我们代码的阅读性,这个就看大家的取舍了。
示例:
package mainimport "fmt"func main() { var res1 int = 0 res1 = fuzhi() fmt.Println(res1) fmt.Println("----------") res2 := fuzhi() fmt.Println(res2)}func fuzhi() int { var a = 100 return a}
结果:
Go语言也是支持匿名函数,即闭包。跟其他语言的闭包用法也是大同小异。
示例:
package mainimport "fmt"func main() { clo := closure() fmt.Println(clo()) fmt.Println(clo()) fmt.Println(clo())}/**定义一个闭包示例函数创建closure()函数,内嵌一个返回函数(匿名)该匿名函数实现 i 自增 */func closure() func() int { i := 0 return func() int { i += 1 return i }}
结果:
使用闭包,最大一个好处就是可以直接使用闭包函数内的变量,不需要重新申明。
Go语言支持多维数组,这个还是比较有特点的,声明方式如下:
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
示例:
var thrDim1 [3][2] intvar thrDim2 [3][4][3] int
在我们实际使用中,用得最多的是二维和三维数组。
下面我们写几个代码试试,看看效果。
package mainimport "fmt"func main() { // 第一种使用示例 var thrDim1 = [3][4]int{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} fmt.Println(thrDim1[0][0]) // 第二种使用示例 thrDim2 := [3][4]int{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} fmt.Println(thrDim2[1][1]) // 第三种使用示例 thrDim3 := [][]int{} r1 := []int{1,2,3} r2 := []int{4,5,6} // 使用append()函数将一维数组添加到多维数组 thrDim3 = append(thrDim3,r1) thrDim3 = append(thrDim3,r2) fmt.Println(thrDim3[0][1])}
运行结果:
指针这概念,自己在学C系的编程语言的时候接触比较多,没想到Go语言这里也有。
什么是指针?一个指针变量指向了一个值的内存地址。Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。
指针声明格式如下:
var var_name *var-type
说明:
var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。
示例:
package mainimport "fmt"func main() { var a int = 1 fmt.Println(&a)}
运行结果:
结构体可以为不同项定义不同的数据类型,类似Java的实体对象类一样。这和数组是有一点不同,数组一般都是存储相同类型的数据。
结构体格式如下:
type struct_variable_type struct {
member definition
member definition
...
member definition
}
结构体定义需要使用type和struct语句。
示例:
package main
import "fmt"
type People struct {
name string
age int
}
func main() {
// 直接赋值
fmt.Println(People{"zhangsan", 10})
// key-value方式赋值
fmt.Println(People{name: "lisi", age: 15})
// 可以按需赋值
fmt.Println(People{name: "zhaowu"})
fmt.Println(People{age: 20})
}
运行结果:
从上面效果来看,go语言的结构体用法和Java的对象概念很接近,其余用法也类似Java的,这里就不详细讲解了。
相信Java开发的朋友,对这个都不陌生,数据格式一般都是Key-Value方式,在Go语言这里,也是不例外,也是Key-Value方式。不过它的展现形式还是有点不一样,声明格式如下:
var map_variable map[key_data_type]value_data_type
我们先写个demo看看:
package main
import "fmt"
func main() {
var people map[string]string
people ["张三"] = "zhangsan"
people ["李四"] = "lisi"
fmt.Println(people["李四"])
}
运行后,发现报错了:
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
E:/ispeasant/github/bwzydy4learn/Go/GoDemo/myMathPackage/demo7.go:8 +0x32
Process finished with the exit code 2
这是因为Go语言中的map,未初始化时默认是nil,如果直接写入数据,是会报错的。因此,我们在声明map后,需要对它进行初始化,可以通过make函数对它初始化。
修正后:
package main
import "fmt"
func main() {
// 先声明
var people map[string]string
// 再使用make函数对其进行初始化
people = make(map[string]string)
people ["张三"] = "zhangsan"
people ["李四"] = "lisi"
fmt.Println(people["李四"])
}
运行效果如下:
lisi
Process finished with the exit code 0
就这个相对比较特殊,其余api练习,这里就不一一展示了。
Go语言的make函数,还是有点新奇的,你可以理解为Java语言中的new。Go语言中的make函数,是内建函数,主要用来为slice、map或chan类型分配内存和初始化对象,也只能用于这三种类型。
Go语言也有类似Java语言的接口,但Go语言更强调的是数据类型即接口,把类似的方法放在一起,当我们需要实现这些方法的时候,只需要实现这个接口即可。
示例:
package main
import "fmt"
// 定义接口
type PeopleDemo interface {
speak()
}
// 定义结构体
type ZhangSan struct {
}
// 实现接口方法
func (zhangsan ZhangSan) speak() {
fmt.Println("我是张三")
}
func main() {
var people PeopleDemo = new(ZhangSan)
people.speak()
}
运行结果:
但在我学习过程中,让我有点好奇的是,为什么必须定义结构体,而且实现接口的时候,为什么需要传入结构体?先把问题放在这里,后续在学习过程中,看能否找到答案。
让我决定学Go语言,主要是大家都说Go语言的并发能力很厉害,而且使用很方便,所以自己就开始接触Go语言。
Go语言使用并发,很简单,就是用go这个关键字来启动,我们先看看示例:
package main
import (
"fmt"
"time"
)
func speak(info string) {
// 为了方便测试,让代码循环执行多次,并每次中间有等待时间
for i := 0; i < 10; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(info)
}
}
func main() {
speak("A")
speak("B")
}
运行效果:
A
A
A
A
A
A
A
A
A
A
B
B
B
B
B
B
B
B
B
B
Process finished with the exit code 0
因此,可以看出,speak()这个方法是串行执行,并不是并行执行,那我们把第一个speak()方法用并发方式来执行看看。
代码:
package main
import (
"fmt"
"time"
)
func speak(info string) {
// 为了方便测试,让代码循环执行多次,并每次中间有等待时间
for i := 0; i < 10; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(info)
}
}
func main() {
go speak("A")
speak("B")
}
运行效果:
B
A
A
B
A
B
B
A
A
B
B
A
A
B
B
A
B
A
A
B
Process finished with the exit code 0
因此,我们可以看出,并不是先执行完第一个方法后再执行第二个,而是没有固定先后顺序,证明我们的并发方式是有效的。
到此为止,我们基本把Go语言的基础内容都过了一遍,当然只掌握这些,是不够用于项目中,后续我们还是需要加深的去研究。后续有新的内容,再与大家分享。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。