前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言-学习笔记

Go语言-学习笔记

原创
作者头像
不务正业的猿
发布2022-03-23 11:27:20
6640
发布2022-03-23 11:27:20
举报
文章被收录于专栏:不务正业的猿

概述

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”输入以下代码:

代码语言:javascript
复制
package mainimport "fmt"func main() {	fmt.Println("Hello World")}

就是最简单的“Hello World”代码。

在“HelloWorld.go”当前目录,打开命令控制台,执行以下命令:

代码语言:javascript
复制
go run HelloWorld.go

如图:

因此,我们的Go环境,是已经安装好。

另外,如果大家在控制台不能直接执行“go”命令,则有可能没有配置环境变量。但我自己发现一个现象,好像win10后,安装java或者python的时候,都会自动添加到环境变量,不需要自己配置,我自己这次安装go环境也是,都是直接帮我添加好环境变量。

如果没有添加,则需要我们自己手动添加,大致如下:

新建系统环境变量:

起个变量名,变量值为Go环境的安装目录:

最后修改系统变量的path,如下:

Go语言开发工具

因为我自己已经有Java开发语言的基础,根据经验,不同的编程语言,基础语法会有所不同,但应该都是大同小异。所以,就没必要向零基础那样学习方式,先大概了解一下所有内容,后续我们再根据实际情况来加深学习。

为了更好的使用Go语言,我们还是需要先安装好开发工具,提高我们的编码效率。

LiteIDE

首先试一下这个开源的工具,官网地址:https://sourceforge.net/projects/liteide/

下载回来之后,直接解压就可以使用。

找到上面这个执行文件,直接双击打开就可以使用。

在使用过程中,需要注意的一些细节。

第一:这里要选择自己系统的版本。

第二:如果执行的时候,报以下错误:

代码语言:javascript
复制
go: cannot find GOROOT directory: c:\go

则需要配置运行环境。从这里点击打开。

把这里修改成你自己的Go环境的安装路径:

第三:如果在运行的过程中,报以下错误:

代码语言:javascript
复制
go: cannot find main module, but found .git/config in....

则可按照以下方法来解决:

在自己的命令控制台,执行以下命令:

代码语言:javascript
复制
go env -w GO111MODULE=off

GoLand

GoLand 是 Jetbrains 家族的 Go 语言 IDE,Jetbrains产品的口碑,一直都是挺好的,就是收费贵而已,安装那些流程就免了。

那我们在GoLand写一个“Hello World"试一下,看看是什么效果。

新建一个projec:

配置路径:

新建一个go file的空文件:

编写最简单的“Hello World”代码:

代码语言:javascript
复制
package TestGoLand01import "fmt"func main()  {   fmt.Println("Hello World")}

然后,运行看看效果:

弹出以上窗口,先不管它,直接继续”Run“。

代码语言:javascript
复制
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 版本不兼容。请查看计算机的系统信息,然后联系软件发布者。

百度一番之后,说这里出了问题。

按照网上的操作,改成以下情况:

代码语言:javascript
复制
package mainimport "fmt"func main()  {   fmt.Println("Hello World")}

然后再运行:

Goland的安装好像成功了,后续在学习过程中,再深入研究。

Go基础

因为我自己是有其它编程语言的基础,为了更加快速学习,我这里记录我自己觉得稍微值得关注的知识点。

Hello World例子说明

Hello World例子:

代码语言:javascript
复制
package mainimport "fmt"func main()  {   fmt.Println("Hello World")}

“package main”定义了包名,必须在第一行指明这个文件属于哪个包,“package main”表示一个可独立执行的程序,而且每个Go应用程序都包含一个名为“main”的包,这类似程序的入口。

{的问题

Go语言的“{”是不能单独一行的,不然会报以下错误:

代码语言:javascript
复制
# 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

iota,是go语言里的常量计数器,只能在常量的表达式里使用。

iota在const关键字出现时将被重置为0(const内部的第一行之前),const中每新增一行常量声明将使iota计数一次。

iota可以理解为const语句块中的行索引。

使用方式如下:

代码语言:javascript
复制
const(   a = iota   b = iota   c = iota   d = iota)fmt.Println(a,b,c,d)

执行结果为:

代码语言:javascript
复制
0 1 2 3

当然,大家也可以采用简化形式:

代码语言:javascript
复制
const(   a1 = iota   b1   c1   d1)fmt.Println(a1,b1,c1,d1)

执行结果为:

代码语言:javascript
复制
0 1 2 3

如果常量里有其它数据类型,会是什么情况?

代码语言:javascript
复制
const(   a2 = iota   b2   c2   d2   e2 = "e2"   f2   g2)fmt.Println(a2,b2,c2,d2,e2,f2,g2)

其中e2为字符串类型,并赋值,那我们执行看看是什么现象。

代码语言:javascript
复制
0 1 2 3 e2 e2 e2

可以看到,f2和g2并不会继续自增。

那如果是下面这样呢?

代码语言:javascript
复制
const(   a3 = iota   b3   c3   d3   e3 = "e3"   f3 = iota   g3)fmt.Println(a3,b3,c3,d3,e3,f3,g3)

我们把f3重新设置为iota。

执行结果如下:

代码语言:javascript
复制
0 1 2 3 e3 5 6

可以看到,f3和g3会重新自增,而且和他们当前行的索引是一致。

Go语言中=和:=的区别

=是赋值,:=是声明变量并赋值。:=这个对于我们Java开发工程师来说,一开始可能会有点不习惯,但对于Go语言来说,它确实挺方便的。

:=是通过系统自动推断类型,不需要var关键字,可以简化我们代码,当然可能会影响我们代码的阅读性,这个就看大家的取舍了。

示例:

代码语言:javascript
复制
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语言也是支持匿名函数,即闭包。跟其他语言的闭包用法也是大同小异。

示例:

代码语言:javascript
复制
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语言支持多维数组,这个还是比较有特点的,声明方式如下:

代码语言:javascript
复制
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

示例:

代码语言:javascript
复制
var thrDim1 [3][2] intvar thrDim2 [3][4][3] int

在我们实际使用中,用得最多的是二维和三维数组。

下面我们写几个代码试试,看看效果。

代码语言:javascript
复制
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语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。

指针声明格式如下:

代码语言:javascript
复制
var var_name *var-type

说明:

var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。

示例:

代码语言:javascript
复制
package mainimport "fmt"func main()  {   var a int = 1   fmt.Println(&a)}

运行结果:

结构体

结构体可以为不同项定义不同的数据类型,类似Java的实体对象类一样。这和数组是有一点不同,数组一般都是存储相同类型的数据。

结构体格式如下:

代码语言:javascript
复制
type struct_variable_type struct {    
    member definition    
    member definition    
    ...    
    member definition 
}

结构体定义需要使用type和struct语句。

示例:

代码语言:javascript
复制
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的,这里就不详细讲解了。

Map(集合)

相信Java开发的朋友,对这个都不陌生,数据格式一般都是Key-Value方式,在Go语言这里,也是不例外,也是Key-Value方式。不过它的展现形式还是有点不一样,声明格式如下:

代码语言:javascript
复制
var map_variable map[key_data_type]value_data_type

我们先写个demo看看:

代码语言:javascript
复制
package main

import "fmt"

func main() {
   var people map[string]string

   people ["张三"] = "zhangsan"
   people ["李四"] = "lisi"

   fmt.Println(people["李四"])
}

运行后,发现报错了:

代码语言:javascript
复制
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函数对它初始化。

修正后:

代码语言:javascript
复制
package main

import "fmt"

func main() {
   // 先声明
   var people map[string]string
   // 再使用make函数对其进行初始化
   people = make(map[string]string)


   people ["张三"] = "zhangsan"
   people ["李四"] = "lisi"

   fmt.Println(people["李四"])
}

运行效果如下:

代码语言:javascript
复制
lisi

Process finished with the exit code 0

就这个相对比较特殊,其余api练习,这里就不一一展示了。

make函数

Go语言的make函数,还是有点新奇的,你可以理解为Java语言中的new。Go语言中的make函数,是内建函数,主要用来为slice、map或chan类型分配内存和初始化对象,也只能用于这三种类型。

接口

Go语言也有类似Java语言的接口,但Go语言更强调的是数据类型即接口,把类似的方法放在一起,当我们需要实现这些方法的时候,只需要实现这个接口即可。

示例:

代码语言:javascript
复制
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这个关键字来启动,我们先看看示例:

代码语言:javascript
复制
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")
}

运行效果:

代码语言:javascript
复制
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()方法用并发方式来执行看看。

代码:

代码语言:javascript
复制
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")
}

运行效果:

代码语言:javascript
复制
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 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 安装环境
  • Go语言开发工具
    • LiteIDE
      • GoLand
      • Go基础
        • Hello World例子说明
          • {的问题
            • iota
              • Go语言中=和:=的区别
                • 闭包
                  • 多维数组
                    • 指针
                      • 结构体
                        • Map(集合)
                          • make函数
                            • 接口
                              • 并发
                              • 总结
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档