GO语言入门指南(上)|青训营(实践)

56 阅读15分钟

1 学习前提介绍

语言使用常见命令与操作解释
cd   改变当前工作目录("Change Directory"的缩写)
dir dir是一个常用的命令,用于在命令行界面(如Windows的命令提示符或PowerShell)中列出当前目录中的文件和文件夹。(英文全称是"directory",它是"目录"的缩写)
./ 当前目录
/  下一子目录
../ 父级目录
e: c: d:  切换盘符
cd / 切换到根目录
ls list进行文件的展示
​
go run main.go(对应go代码文件)  进行命令行的Go代码运行 //前提是添加好了go.exe的环境变量 
go build  对某个项目进行构建编译,形成可执行文件.exe  与go run一样仅对可执行文件
go build -o  其他文件名.exe  形成其他名字的可执行文件
go install  编译项目,对main生成的可执行文件,放置在父文件夹的bin文件中,生成.exe文件
                    对包文件(内放函数)生成.a文件(静态库文件),放在父文件夹的pkg文件中
    (`go install` 是 Go 语言提供的一个命令行工具,用于构建并安装可执行文件或库文件。
​
    当你运行 `go install` 命令时,它会编译你的代码,并将生成的可执行文件或库文件安装到 Go 工    作区的 `bin` 目录或 `pkg` 目录中,具体取决于你的代码是可执行程序还是库。
​
    如果你的代码是一个可执行程序,`go install` 会将编译后的程序安装到 Go 工作区的 `bin` 目录    中。你可以在命令行中直接运行该可执行文件。
​
    如果你的代码是一个库文件,`go install` 会将编译后的库安装到 Go 工作区的 `pkg` 目录中。其    他项目可以通过导入该库来使用它。
​
    在运行 `go install` 命令之前,需要确保你的代码可以成功编译并通过构建。在代码的根目录中运行     go build` 命令可以验证代码是否可以正确构建,如果成功构建,则可以继续运行 `go              install` 命  令进行安装。
​
    安装的文件将被放置在 `$GOPATH` 或 `$GOBIN` 环境变量指定的目录中。如果你没有设置这些环境    变量,它们的默认值分别是 `$HOME/go` 和 `$GOPATH/bin`。
​
    使用 `go install` 命令可以方便地构建和安装你的 Go 代码,并使其可被其他项目引用和运行。)
    即可以生成包文件,供其他项目进行调用,也可以生成可执行文件,用来让用户使用
    一般进入到项目处,再执行该命令,也可以进入到项目的父级目录中在命令尾处加上项目名
    go run 运行项目代码,内部会先编译并将编译后的文件放在系统的临时目录,然后再自动执行
    go build 运行项目代码,手动编译并生成一个可执行文件,然后自动执行
    go install 生成可执行代码+包文件,并且会将编译后的文件放在bin/pkg目录  
    go run:该命令用于直接运行一个 Go 源代码文件(.go 文件)。它会在临时目录中编译和执行代码,不会生成可执行文件。这对于临时测试和执行简单的程序很有用。
​
    go build:该命令用于编译 Go 程序,并生成一个可执行文件。它会将指定的源代码文件编译为二进制文件,并将可执行文件放在当前目录中。如果没有指定输出文件名,默认会使用源文件的文件名(去除扩展名)作为可执行文件名。
​
    go install:该命令用于编译 Go 程序,并将可执行文件安装到工作空间($GOPATH/bin)或 Go 安装路径中。它会先将代码编译为二进制文件,然后将可执行文件复制到指定的目标路径中。这个命令常用于将可执行文件安装到系统路径中,以便可以在任何地方执行该程序。
    go build 主要用于生成可执行文件,并放置在当前目录下,而 go install 则是将可执行文件安装到系统路径中,方便在终端中直接运行
​
综上所述,go run 用于临时运行代码,go build 用于编译生成可执行文件,go install 用于编译生成可执行文件并安装到系统路径中。
    go version  查看版本信息
    -bin 编译后的可执行文件
    -pkg 编译后的包文件
    -src 项目代码
    环境变量
    GOROOT  go编译器安装目录
    GOPATH  用于存放的编译后的可执行文件 编译后的包文件 项目代码 (go 1.11版本后,go mod功能,可以不用放在GOPATH)
    GOBIN   编译后的可执行文件存放位置
​
​

环境搭建

编译器语言:c,c++,go,java 全文翻译(全写完,再去编译翻译)

解释器语言:Python,php,javascript,ruby 实时翻译(写一句翻译一句)

  • 开发工具选择

    • IDE的全称是集成开发环境(Integrated Development Environment)
    • Goland(IDE,是专属Go的开发工具,拥有相应齐全的功能库)
    • Vscode(拥有较多的第三方库,本身没有功能)

初识包管理

关于包管理的总结:

  • 一个文件夹可以称为一个包

  • 在文件夹(包)中可以创建多个文件

  • 在同一个包下的每一个文件中必须指定包名称且相同

    • 包的名称 package :xx 最好是与父文件夹(包)名字一样
    • 如果不一样,也可以,但要求每一个子文件都相同,一般要求一样,除了main

重点:关于包的分类

  • package main

    • main包中,必须写一个main函数,此函数是项目的入口(main主函数)
    • 有main包且有main函数,编译生成会得到一个可执行文件.否则生成的是包文件
  • 非main包

    • 用来将代码进行分类,一个大功能一个包
    • 同一个包中的文件,可以之间相互调用函数
  • 在进行编译运行的时候,可以选择编译的种类

    • 文件 仅编译运行单文件
    • 包 运行该文件的父级包下的所有文件
    • 目录 对应路径下的全部文件都会进行编译
  • 同一包下的文件之间的调用

    • 归属于同一个包,那么可以直接调用,编译执行时设置成,编译整个包即可

    • 归属于同一个祖父包,但不同的父级包,那么可以通过导入对应的包即可

      • -GrandFather
          -father
            -baidu.go
            -google.go
          -main
            -main.go  在该.go代码中调用baidu.go方法应该要导包
                            import"GrandFather/father"  
                            father.baidu()
                            father.google()
            -city.go
        
      • 包管理中的命名,如果方法名首字母大写,则认为是可以共用的public,而小写则认为无法共用,为private

2 特性知识介绍

GO语言简介

  • Golang的称呼是由于Go语言在注册站点地址使用时,其域名go已被注册,故只能改成go language取合并就是golang了,golang只是一个网站域名,标签,语言称呼为go语言,也可以理解为golang只是go语言的另一个称呼

  • 谷歌出品的一门高级语言

  • 在计算机科学中,脚本一词最早用于描述一类逐行解释和执行的计算机程序。它们不需要编译成机器码,而是由解释器按照语法规则一行一行地解释和执行。

  • 脚本语言的概念在上世纪60年代末开始出现。最早的脚本语言之一是Unix操作系统中的Shell脚本语言,它允许用户编写一系列的命令,用于自动化和批处理任务。

    随着计算机应用的发展,脚本逐渐成为一种常见的编程方式。它们通常具有简单易学的语法,可以快速编写和调试,以及自动化一些重复性的任务。脚本语言的发展也为网页交互、系统管理、自动化测试等方面提供了便利。

    因此,脚本一词在计算机领域中被广泛使用,用于描述这种解释执行的编程方式,即将一系列指令按照特定规则组织起来,通过解释器逐行执行的计算机程序。

    一些常见的脚本语言包括Shell脚本、Python、JavaScript、Ruby、Perl等。

  • 特点

    • 高性能,高并发
    • 语法简单,学习曲线平缓
    • 丰富的标准库(减少第三方库的使用)
    • 完善的工具链
    • 静态链接
    • 快速编译,几乎拥有最快编译速度的语言
    • 跨平台
    • 垃圾回收
  • 使用公司

    • 字节跳动,腾讯,美团,滴滴,百度,谷歌,facebook,哔哩哔哩等均为使用,字节跳动全面拥化go语言

    • 字节跳动背景

      • 最初使用python,由于性能问题转化为go
      • c++不适合在线Web服务
      • 早期团队非java背景
      • go的性能更好,部署简单,内部RPC,HTTP框架的推广

3 基础语法

3.1 从Hello world走进Go语言

如果说有什么是一个程序员上手一门新语言的重要一环,那一定是用新语言输出Hello,world无疑了。那么,今天就让我们从这个新语言入门标志出发,开始我们Go语言的学习之旅。

打印Hello,world的Go语言代码如下:

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

这是Go语言中较为简单的一类代码。但麻雀虽小,五脏俱全。先看第一行package,顾名而思义,肯定指的就是一种包,具体而言,当然就是我们这里的main包了。实际上在Go语言中,package就是其源代码的一个集合,像os、io,以及后面的fmt都是这样的一个包。那么它在使用时有哪些注意事项呢?

  • 使用main包时,即为使用应用程序的入口包,编译后会得到一个可执行文件,至于其他的包则没有这个效果
  • 可以自定义包,看作是一个存放.go文件的文件夹,该文件夹下所有go文件都要在第一行添加
import {
    "fmt"
}

再看第二行,我们用到了import,这就又牵涉到包的另一种操作,包的导入。这是为了在文件中引用其他包的内容,这里就有点像我们c语言中的include添加头文件的用法。

最后就是我们代码的主题部分:在main函数中调用fmt包中的输出函数Println,实现对Hello,world的打印。

简单总结下:为了使程序可执行,我们在一开始声明了main包,然后为了使用标准输出函数,我们又导入了fmt包,最后调用fmt中的Println,实现打印Hello,world。顺带提一句,如果要实现程序的运行,只需要在命令行里输入go run 文件地址,即可。

3.2 变量

//两种声明变量的方式
var a ="Hello,world"//或者var a string ="Hello,world"
a:="Hello,world"
package main  //属于main包的一部分(程序的入口文件)

import(
"fmt"  // fmt包为格式化字符串,在屏幕输出字符串
)
func main(){
fmt.Println("hello world")
}
从以上两种方式可以看出,Go语言作为一门高级语言,具有自动推导类型的功能,因此,也就不必写出具体变量类型,但如果要写,应注意类型名在变量名后。另外一个细节,在前面没有var时,赋值所用为":=",而非"="

3.3 语句

  • 对整个文件进行格式化:Ctrl + Alt + L

  • 在 Go 语言中,var f = float32(e)f := float32(e) 是有细微差别的。

    • var f = float32(e) 是一种使用 var 关键字声明变量并赋值的语法。它会显式地声明一个类型为 float32 的变量 f,并将 e 的值转换为 float32 类型进行赋值。
    • f := float32(e) 是一种使用短变量声明语法声明变量并赋值的方式。它会根据 e 的值及其类型自动推断 f 的类型,并将 e 的值转换为 float32 类型进行赋值。

    在大多数情况下,这两种语法是等效的,它们都将 e 的值转换为 float32 类型并赋给 f

    然而,这两种语法在某些特殊场景下有一些微妙的差别。例如,:= 的短变量声明语法只能在函数内部使用,而 var 关键字可以在函数内外使用。另外,:= 还可以用于声明多个变量,而 var 关键字则需要每个变量单独声明。

    综上所述,虽然 var f = float32(e)f := float32(e) 在大多数情况下是等效的,但在一些特定场景下可能存在细微的差别。

  • if else

    if else 与c++中基本相似
    不同于
    if 7%2==0{
    ​
    }else{
    ​
    }   if 后面的判断不需要(),若写了(),编译器在代码保存时会自动去掉,然后要紧跟{}  
    
  • 循环

    • go中没有while,do-while循环,拥有的是for循环
      其结构与c++中也相似,同样也不需要()来包裹限制条件
      for j:=1;j<7;j++{
      ​
      }
      for{
      ​
      } 什么都不写代表死循环
      for i<=3{
      ​
      }只留下界限条件也可以
      
  • switch分支结构

    • switch a (无需括号){
      case 1:
           语句体
      case 2:
           语句体
      default:
          
      }
      ​
      注意的是,go中无需break语句,一旦case选中直接跳出
      甚至于无需条件语句,switch用来替换ifelse语句
      switch{
      case t.Hour()<12:
          ...
      default :
        ....    
      }
      
  • 在Go语言中,分号是可选的,因为Go编译器会根据换行符来判断语句的结束。换行符会被视为语句的结束符,不需要使用分号来显式表示语句的终止。,使用换行符来隐式表示语句的结束是Go语言编程的常规做法。

    • 然而,如果你希望在一行中写多个语句,可以使用分号将它们分隔开,例如:

      fmt.Println("Hello"); fmt.Println("World")
      
  • python是通过缩进来控制语句归属关系的,通过分行符来控制语句的结束

    • c语言通过{}来控制语句归属关系,通过分号;来控制语句结束
    • go语言结合二者通过{}来控制语句归属关系,通过分行符来控制语句结束

3.4 数组与切片

数组和c语言中的类似,只需要记住它在Go语言中的类型是[n]+元素类型

而切片是一类可变长度的数组,常见操作如下:

//声明和赋值
s := make([]string,5)
s[0] = "a"
//追加
s = append(s,"g")
  • 数组定义

    • 静态数组,长度固定
      var a [5]int
      len(a) 读取长度
      a[4]  正常索引
      var two[2][3]int  二维数组
      直接定义
      b := [5]int{1,2,3,4,5}
      fmt.Println(b)  直接打印数组全部
      fmt.Println(变量,常量,...)可以在一行内打印,以空格隔开
      ​
      
  • 切片(动态数组)

    • s:=make([]string,3)  //创建字符切片,大小容量为3
      s[0]="a"
      s = append(s,"d","e"...)  方法
      c :=make([]string,len(s))  make方法创建新切片
      copy(c,s)  copy方法进行切片复制,后者向前者
      fmt.Println(s[2:5])  输出s[2]-s[5]
      fmt.Println(s[:5])   输出到s[5]
      fmt.Println(s[2:])   从s[2]开始输出
      good := []string{"g","o","o","d"}  不用make方法创建而是直接定义切片
      

3.5 map(字典\哈希\键值对)

就是其他语言中的字典,重点在于key和value的对应,以下是它的常见操作:

m := make(map[int]string)
m[1] = "one"
fmt.Println(r,ok)//r是一个value,此处用于表示判断r是否在m中
delete(m,1)
m :=make(map[string]int)  用make方法进行创建map
m["one"]=1
m["two"]=2
fmt.Println(m)  //map[one:1 two:2]
fmt,Println(len(m)) //2
fmt.Println(m["one"])  //1
fmt.Println(m["unknow"])  //0  未有的键所给的值默认为0

r,ok :=m["unknow"]  //利用ok 布尔变量来获取其是否存在,是则true,否则false  r来获取键所对应的值
 
delete(m,"one")  delete方法来删除
m2 := map[string]int{"one":1,"two":2}
var m2 = map[string]int{"one":1,"two":2}

3.6 range关键字的快速遍历

nums := []int{2,3,4}
sum :=0
for i,num :=range nums{   //遍历的时候是i代表索引,num代表数值,
  sum+=num
  if num==2{  
  fmt.Println("index:",i,"num:",num)//index: 0 num: 2
  }
}

m := map[string]string{"a":"A","b":"B"}
for k,v :=range m{  //map则遍历键值对
fmt.println(k,v) //b B; a A
}
for k :=range m{
fmt.Println(k) // a b   如果只是一个则为键   如果不需要可以通过_来忽略
}

3.7 函数与指针的使用

函数的基本使用与举例

func 方法来创建函数
func add(a,b int)int{
return a+b
}
func add1(a int,b int)int{
return a+b
}  //可分别定义,也可一起定义

func exists(m map[string]string,k string)(v string,ok,bool){
v,ok=m[k]
return v,ok    //go中可以进行多值返回操作,且业务中一般返回多值,第一个为需求值,第二个为错误信息,反馈信息

}
func main(){
res:=add(1,2)
fmt.Println(res)
v,ok :=exists(map[string]string{"a":"A"},"a")
fmt.Println(v,ok)
}

go语言中习惯将变量类型写在后面

指针的基本使用与举例

func add2(n int){
n+=2
}
func add2ptr(n *int){
*n+=2
}  

与c语言中类似,用int来定义指针,就是的顺序在类型的前面,而c中为 int * n 可以理解为go的定义与c中的对称,正好前后相反 同样是&取地址