Golang入门

Golang准备

学习方向:

Go语言的特点:

Go语言保证了既能达到静态编译语言的安全和性能,又达到了动态语言开发维护的高效率,使用一个表达式来形容Go语言,Go=C + Python,说明Go语言既有C静态语言程序的运行速度,又能达到Python动态语言的快速开发。

1.从c语言中继承了很多理念,包括表达式语法,控制结构,基础数据类型,调用参数传值,指针等等,也保留了和c语言一样的编译执行方式及弱化的指针。

2.引入包的概念,用于组织程序结构,Go语言的一个文件都要归属于一个包,而不能单独存在。

3.垃圾回收机制,内存自动回收,不需要开发人员管理。

4.天然并发

(1)从语言层面支持并发实现简单

(2)goroutine,轻量级线程,可实现大并发处理,高效利用多核。

(3)基于CSP并发模型(Comminicating Sequential Processes)实现。

5.吸收管道通信机制,形成Go语言特有的管道channel通过管道channel,可以实现不同的goroute之间的相互通信。

6.函数返回多个值。

7.新的创新:比如切片slice、延时执行defer等。

环境配置:

image-20220116161005657

GoLand和VSCode安装

Golang入门

go的目录结构

Golang入门_第1张图片

hello world

package main

import "fmt"

func main() {
   fmt.Println("hello world")
}
  1. go文件的后缀是 .go

  2. package main 表示该 hello.go 文件所在的包是main,在go中,每个文件都必须归属一个包。

  3. import “fmt” 表示引入一个包,包名fmt,引入该包后,就可以使用fmt包的函数,比如:fmt.Println

  4. func main(){} func 是一个关键字,表示一个函数。main是函数名,是一个主函数,即我们程序的入口。

  5. fmt.Println(“hello world”) 表示调用fmt包的函数Println输出"hello world"

通过go build + 文件名 编译文件

生成.exe 可执行文件

go run + 文件名

直接运行

linux下的Go程序

linux下开发go和windows开发基本一样。只是在运行可以执行的程序时,是以 ./文件名方式

Golang执行流程的分析

Golang入门_第2张图片

两种执行流程的方式区别

1.如果我们先编译生成了可执行文件,那么我们可以将可执行文件拷贝到没有go开发环境的机器上,任然可以执行。

2.如果我是直接go run go源代码,那么如果要在另一个机器上运行,也想要go开发环境,否则无法执行。

3.在编译时,编译器会将程序运行依赖的库文件包含在可执行文件中,所有可执行文件变大了很多。

Golang入门_第3张图片

编译和运行

自主命名:

go build -o 生成文件名.exe 源文件.go

Golang入门_第4张图片

注意事项

Golang入门_第5张图片

1.Go源文件以“go”为扩展名

2.Go应用程序的执行入口是main()函数。

3.Go语言是严格区分大小写的。

4.Go方法由一条条语句构成,每个语句后不需要分号(Go语言会在没行后自动加分号),这也体现出了Golang的简洁性。

5.Go编译器是一行行进行编译的,因此我们一行就写一条语句,不能把多条语句写在同一行,否则会报错。

6.Go语言定义的变量或者import包如果没有使用到,代码不能编译通过。

7.大括号都是成对出现的,缺一不可。

GO语言常用的转义字符

和c语言类似

转义字符:
\n (换行)
\t (表示一个制表符,通常使用它可以排版)
\ (转义)
\r (回车,表示从当前行的最前面开始输出,覆盖掉以前内容)

Go语言注释

行注释: //

块注释: /**/

规范的代码风格

正确的注释和注释风格

Go官方推荐使用行注释

正确的缩进和空白

1.使用一次tab操作,实现缩进,默认整体向右移动,有时候shift+tab整体向左移动。

2.或使用gofmt来进行格式化

3.运算符两边习惯性各加一个空格。

4.大括号的写法

Golang入门_第6张图片

5.换行用逗号(,)

Golang入门_第7张图片

变量

变量是程序的基本组成单位

概念:

变量相当于内存中一个数据存储空间的表示,通过变量名可以访问到变量值。

声明变量:

var 变量名 数据类型

package main

import "fmt"

func main() {
   var i int = 10
   fmt.Println(i)
}

使用的注意事项

1.变量表示内存中的一个存储区域

2.该区域有自己的名称(变量名)和类型(数据类型)

3.Golang变量使用的三种方式

(1)指定变量类型,声明后若不赋值,使用默认值

(2)根据值自行判定变量类型(类型推导)

(3)省略var,注意:=左侧的变量不应该事故已声明过的,否则会导致编译错误

4.多变量声明,在编译值,有时候我们需要一次性声明多个变量,Golang也提供这样的语法。

5.该区域的数据值可以在同一类型范围内不断变化

6.变量在同一个作用域内不能重名

7变量=变量名+值+数据类型

8.Golang的变量如果没有赋初值,会赋一个默认值。

package main

import "fmt"

var n7 = 100
var n8 = 200
var name2 = "jt"

//一次声明
var (
	n9    = 100
	n10   = 200
	name3 = "jt"
)

func main() {
	//golang的变量使用方式1
	//第一种:指定变量类型,声明后若不赋值,使用默认值// int的默认值是e,其它数据类型的默认值后面马上介绍var i int
	var i int
	fmt.Println("i =", i)

	//第二种:根据值自行判定变量类型(类型推导)var num =10.11
	var num = 10.11
	fmt.Println("num =", num)

	//第三种:省略var,注意:=左侧的变量不应该是已经声明过的,香则会导致编译错误1/下面的方式等价var name stringname = "tom"
	// :=的:不能省略,否则错误
	name := "tom"
	fmt.Println("name =", name)

	//该案例演示golang如何一次性声明多个变量
	var n1, n2, n3 int
	fmt.Println(n1, n2, n3)

	// 一次性声明多个变量的方式2
	var n5, name1, n4 = 108, "tom", 888
	fmt.Println(n5, name1, n4)

	//一次性声明多个变量的方式3,同样可以使用类型推导
	n5, name1, n4 = 108, "tom", 888
	fmt.Println(n5, name1, n4)

	//输出全局变量
	fmt.Println(n7, name2, n8)
	fmt.Println(n9, name3, n10)
}

+号的使用

1.当左右两边都是数值型时,则做加法运算

2.当左右两边都是字符串,则做字符串拼接

package main

import "fmt"

//+ 号的使用
func main() {
   var i = 1
   var j = 2
   var r = i + j
   fmt.Println(r)

   var str1 = "hello"
   var str2 = "world"
   var str = str1 + str2
   fmt.Println(str)
}

数据类型

整数类型

类型 有无符号 占用存储空间 数据范围
int8 1字节 -128 ~ 127
int16 2字节 -215 ~ 215-1
int32 4字节 -231 ~ 231-1
int64 8字节 -263 ~ 263-1
uint8 1字节 0 ~ 255
uint16 2字节 0 ~ 216-1
uint32 4字节 0 ~ 232-1
uint64 8字节 0 ~ 264-1
类型 有无符号 数据范围 备注
int -231 ~ 231-1,-263~263-1
uint 0 ~ 232-1,0 ~ 264-1
rune -231 ~ 231-1 等价int32,表示一个Unicode码
byte 0 ~ 255 当要存储字符是选用byte

1.Golang各整数类型分:有符号和无符号,int uint的大小和系统有关。

2.Golang的整型默认声明为int型

fmt.Printf("a 的类型 %T", a)//输出数据类型

3.如何在程序查看某个变量的字节大小和数据类型

fmt.Printf("a 的类型 %T  a 占用的字节数是 %d", a, unsafe.Sizeof(a))//输出字节大小

4.Golang程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。

5.bit:计算机中的最小存储单位。byte:计算机中基本存储单元。1byte = 8 bit

浮点类型

类型 占用存储空间 表数范围
单精度float32 4字节 -3.403E38 ~ 3.403E38
双精度float64 8字节 -1.798E308~ 1.798E308

说明一下:

1)关于浮点数在机器中存放形式的简单说明,浮点数=管号拉+指数位+尾数位3.56

11110000111.111111111111111111000

2)尾数部分可能丢失,造成精度损失。-123.0000901

//尾数部分可能丢失,造成精度损失。
var num3 float32 = -123.0000901
var num4 float64 = -123.0000901
fmt.Println("num3=", num3, "num4=", num4)

3)浮点型的存储分为三部分:符号位+指数位+尾数位在存储过程中,精度会有丢失

浮点型使用细节

  1. Golang浮点类型有固定的范围和字段长度,不受具体oSI操作系统)的影响。
  2. Golang 的浮点型默认声明为float64类型。
  3. 浮点型常量有两种表示形式,十进制数形式:如:5.12 .512(必须有小数点),科学计数法形式:如:5.1234e2 = 5.12*10的2次方5.12E-2 =5.12/10的2次方
  4. 通常情况下,应该使用float64,因为它比float32更精确。

字符类型

Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。

字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,它是由字节组成的。

	var c1 byte = 'a'
	var c2 byte = '0' //字符的0
	//当我们直接输出byte值,就是输出了的对应的字符的码值// "a' ==>
	fmt.Println("c1=", c1)
	fmt.Println("c2=", c2)

	//如果我们希望输出对应字符,需要使用格式化输出
	fmt.Printf("c1=%c c2=%c\n", c1, c2)

	//var c3 byte =‘北’//overflow溢出
	var c3 int = '北' //overflow溢出
	fmt.Printf("c3=%c c3对应码值=%d", c3, c3)

字符类型使用细节

1.字符常量是用单引号(’’)括起来的单个字符。例如: var c1 byte = ‘a’ , var c2 int=“中” var c3 byte = ‘9’

2.Go中允许使用转义字符尘来将其后的字符转变为特殊字符型常量。例如: var c3 char = ‘\n’ // \n表示换行符

3.Go语言的字符使用UTF-8编码,英文字母是1个字节,汉字是3个字节

4.在Go中,字符的本质是一个整数,直接输出时,是该字符对应的UTF-8编码的码值。

5.可以直接给某个变量赋一个数字,然后按格式化输出时%c,会输出该数字对应的unicode字符

6.字符类型是可以进行运算的,相当于一个整数,因为它都

对应有Unicode码.

字符类型本质探讨

  1. 1.字符型存储到计算机中,需要将字符对应的码值(整数)找出来

    存储:字符->对应码值---->二进制–>存储

    读取:二进制---->码值----->字符–>读取

  2. 2.字符和码值的对应关系是通过字符编码表决定的(是规定好)

  3. 3.Go语言的编码都统一成了utf-8。非常的方便,很统一,再也没有编码乱码的困扰了

布尔类型:bool

  1. 布尔类型也叫bool类型,bool类型数据只允许取值true和false
  1. bool类型占1个字节。

  2. bool类型适于逻辑运算,一般用于程序流程控制

布尔使用细节

不可用0或非0的整数代替false和true

字符串数据类型:string

字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本

字符串使用细节

  1. Go语言的字符串的字节使用uTF-8编码标识unicode文本,这样Golang统一使用UTF-8编码,中文乱码问题不会再困扰程序员。

  2. 字符串一旦赋值了,字符串就不能修改了﹔在Go中字符串是不可变的。

  3. 字符串的两种表示形式

    1)双引号,会识别转义字符

    2)反引号(``),以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果

  4. 字符串拼接方式(+)

  5. 当一个拼接的操作很长时,怎么办,可以分行写,但是注意,需要将+保留在上一行.

数据类型的默认值

在go中,数据类型都有一个默认值,当程序员没有赋值时,就会保留默认值,在go中,默认值又叫零值。

数据类型 默认值
整数 0
浮点型 0
字符串 “”
布尔类型 false

基本类型的转换

Golang 和java / c不同,Go在不同类型的变量之间赋值时需要显式转换。也就是说Golang中数据类型不能自动转换

转换语法

表达式T(v)将值v转换为类型T

T:就是数据类型,比如int32,int64,float32等等

v:就是需要转换的变量

细节:

  1. Go中,数据类型的转换可以是从表示范围小–>表示范围大,也可以范围大—>范围小
  2. 被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!
  3. 在转换中,比如将int64 转成int8,编译时不会报错,只是转换的结果是按溢出处理,和我们希望的结果不一样。

练习:

var n1 int32 = 12
var n3 int8
var n4 int8
n4 = int8(n1) + 127 //编译通过,会出现溢出
n3 = int8(n1) + 128 //编译不过
fmt.Println(n3)

基本数据类型和string的转换

基本数据类型转string

方式一: fmt.Sprintf("%参数",表达式)

package main

import "fmt"

func main() {
   var num1 int = 99
   var num2 float32 = 21.11
   var b bool = true
   var mychar byte = 'h'
   var str string //空的str

   //使用第一种方式转换 fmt.Sprintf方法
   str = fmt.Sprintf("%d", num1)
   fmt.Printf("%T,%q\n", str, str)

   str = fmt.Sprintf("%f", num2)
   fmt.Printf("%T,%q\n", str, str)

   str = fmt.Sprintf("%t", b)
   fmt.Printf("%T,%q\n", str, str)

   str = fmt.Sprintf("%c", mychar)
   fmt.Printf("%T,%q", str, str)
}

方式二:使用strconv包的函数

//第二种方式
var num3 int = 99
var num4 float64 = 21.11
var b2 bool = true
str = strconv.FormatInt(int64(num3), 10)
fmt.Printf("%T,%q\n", str, str)

str = strconv.FormatFloat(num4, 'f', 10, 64)
fmt.Printf("%T,%q\n", str, str)

str = strconv.FormatBool(b2)
fmt.Printf("%T,%q\n", str, str)

//strconv包中有一个函数Itoa
var num5 int = 456
str = strconv.Itoa(num5)
fmt.Printf("%T,%q\n", str, str)

string转基本数据类型

1.使用strconvh包的函数

package main

import (
   "fmt"
   "strconv"
)

func main() {
   var str string = "true"
   var b bool
   b, _ = strconv.ParseBool(str)
   fmt.Printf("%T   %v", b, b)

   var str2 string = "12315"
   var n1 int64
   n1, _ = strconv.ParseInt(str2, 10, 64)
   fmt.Printf("%T   %v", n1, n1)

   var str3 string = "213.454"
   var f1 float64
   f1, _ = strconv.ParseFloat(str3, 64)
   fmt.Printf("%T   %v", f1, f1)
}
注意事项

在将String类型转成基本数据类型时,要确保String类型能够转成有效的数据,比如我们可以把"123”,转成一个整数,但是不能把"hello”转成一个整数,如果这样做,Golang直接将其转成0

指针

1.基本数据类型,变量存的就是值,也叫值类型

2.获取变量的地址,用&,比如:var num int,获取num的地址:&num

3.指针类型,指针变量存的是一个地址,这个地址指向的空间存的才是值比如: var ptr *int = &num

4.获取指针类型所指向的值,使用:,比如:var ptr * int,使用ptr获取ptr指向的值

Golang入门_第8张图片

指针使用细节

1.值类型,都有对应的指针类型,形式为*数据类型,比如int的对应的指针就是 * int, float32对应的指针类型就是 *float32,依次类推。

2.值类型包括:基本数据类型int系列, float系列, bool, string、数组和结构体struct

值类型和应用类型

值类型:基本数据类型 int系列, float系列, bool, string 、数组和结构体struct

引用类型。指针、slice切片、map、管道chan、 interface等都是引用类型

Golang入门_第9张图片

标识符

概念

  1. Golang对各种变量、方法、函数等命名时使用的字符序列称为标识符
  2. 凡是自己可以起名字的地方都叫标识符

标识符的命名规则

  1. 由26个英文字母大小写,0-9 ,_组成
  2. 数字不可以开头。
  3. Golang中严格区分大小写。
  4. 标识符不能包含空格。
  5. 下划线"_"本身在Go中是一个特殊的标识符,称为空标识符。可以代表任何其它的标识符,但是它对应的值会被忽略(比如:忽略某个返回值)。所以仅能被作为占位符使用,不能作为标识符使用。
  6. 不能以系统保留关键字作为标识符,比知break,if等等…

保留关键字

Golang入门_第10张图片

标识符注意事项

  1. 包名,保持package的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,不要和标准库不要冲突
  2. 变量名、函数名、常量名:采用驼峰法。
  3. 如果变量名、函数名、常量名首字母大写,则可以被其他的包访间;如果首字母小写,则只能在本包中使用(注:可以简单的理解成,首字母大写是公有的首字母小写是私有的)---->从src后的包开始引用
Golang入门_第11张图片

预定义标识符

Golang入门_第12张图片

运算符

运算符是—种特殊的符号,用以表示数据的运算、赋值和比较等

  1. 算术运算符
  2. 赋值运算符
  3. 比较运算符
  4. 逻辑运算符
  5. 位运算符
  6. 其它运算符

算术运算符

算术运算符是对数值类型的变量进行运算的,比如:加减乘除。在Go程序中使用的非常多。

Golang入门_第13张图片

注意:

i++只能独立使用

Golang 的4+和–只能写在变量的后面,不能写在变量的前面,即,只有 a++ a–没有++a

关系运算符(比较运算符)

  1. 关系运算符的结果都是bool型,也就是要么是true,要么是false
  2. 关系表达式经常用在if结构的条件中或循环结构的条件中
Golang入门_第14张图片

逻辑运算符

用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个bool值。

Golang入门_第15张图片

注意:

&&也叫短路与:如果第一个条件为false,则第二个条件不会判断,最终结果为false

||也叫短路或。如果第一个条件为true,则第二个条件不会判断,最终结果为true

赋值运算符

赋值运算符就是将某个运算后的值,赋给指定的变量。

Golang入门_第16张图片

运算符的优先级

Golang入门_第17张图片

位运算符

Golang入门_第18张图片

其他运算符

image-20220119163527935

原码,反码,补码

1)二进制的最高位是符号位:0表示正数,1表示负数

1 ==>[0000 0001]

-1=>[1000 0001]

2)正数的原码,反码,补码都一样

3)负数的反码=它的原码符号位不变,其它位取反(0->1,1->0)

1=>原码[0000 0001]反码[0000 0001]补码[0000 0001]

-1=>原码[1000 0001]反码[11111110]补码[1111 1111]

4)负数的补码=它的反码+1

5)0的反码,补码都是0

6)在计算机运算的时候,都是以补码的方式来运算的.1-1=1+(-1)

Golang入门_第19张图片

Golang不支持三元运算

键盘输入语句

步骤:

1)导入fmt包

2)调用fmt包的fmt.Scanln()或者fmt.Scanf()

package main

import "fmt"

func main() {
   //方式一:fmt.Scanln
   var name string
   var age byte
   var sal float32
   var isPass bool
   fmt.Println("请输入姓名")
   fmt.Scanln(&name)

   fmt.Println("请输入年龄")
   fmt.Scanln(&age)

   fmt.Println("请输入薪水")
   fmt.Scanln(&sal)

   fmt.Println("请输入是否通过考试")
   fmt.Scanln(&isPass)

   fmt.Println(name, age, sal, isPass)
    
    //方式二:fmt.Scanf
	fmt.Printf("请输入你的名字,年龄,薪水,是否通过考试,使用空格隔开")
	fmt.Scanf("%s %d %f %t", &name, &age, &sal, &isPass)
	fmt.Println(name, age, sal, isPass)
}

流程控制

  1. 顺序控制
  2. 分支控制
  3. 循环控制

顺序控制

程序顺序执行

if分支控制

  1. 单分支(if)
  2. 双分支(if—else)
  3. 多分支(if----if else—else)
  4. 嵌套分支(建议控制在三层内)

注意格式是固定的与其他语言不同

package main

import "fmt"

func main() {
   var i int = 10
   if i > 10 {
      fmt.Printf("i>10")
   } else if i > 20 {
      fmt.Printf("i>20")
   } else {
      fmt.Printf("其他")
   }
}

switch分支结构

switch语句用于基于不同条件执行不同动作,每一个case分支都是唯一的,从上到下逐一测试,直到匹配为止。

golang的case后的表达式可以有多个,使用逗号间隔

匹配项后面也不需要再加break

golang 中的case 语句块不需要写break,因为默认会有,即在默认情况下,当程序执行完case语句块后,就直接退出该switch控制结构。

package main

import "fmt"

func main() {
   var key byte
   fmt.Scanf("%c", &key)
   switch key {
   case 'a':
      fmt.Println("你输入了a")
   case 'b':
      fmt.Println("你输入了b")
   default:
      fmt.Println("输入错误")
   }
}

switch细节

  1. case后是一个表达式(即:常量值、变量、一个有返回值的函数狰都可以)

  2. case后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致

  3. case后面可以带多个表达式,使用逗号间隔。比如case表达式1,表达式2…

  4. case后面的表达式如果是常量值(字面量),则要求不能重复

  5. case后面不需要带break ,程序匹配到一个case后就会执行对应的代码块,然后退出switch,如果一个都匹配不到,则执行default

  6. default语句不是必须的.

  7. switch后也可以不带表达式,类似if --else分支来使用。

Golang入门_第20张图片
  1. switch 后也可以直接声明定义一个变量,分号结束,不推荐。
Golang入门_第21张图片
  1. switch穿透-fallthrough ,如果在case语句块后增加fallthrough ,则会继续执行下一个case,也叫switch穿透。Golang入门_第22张图片

  2. Type Switch: switch 语句还可以被用于type-switch来判断某个interface变量中实际指向的变量类型Golang入门_第23张图片

for循环控制

Golang入门_第24张图片

示例:

package main

import "fmt"

func main() {
   for i := 0; i < 10; i++ {
      fmt.Println("hello word!")
   }
}
package main

import "fmt"

func main() {
   i := 0
   for i < 10 {
      fmt.Println("hello word!")
      i++
   }
}
package main

import "fmt"

func main() {
   i := 0
   for {
      fmt.Println("hello word!")
      i++
      if i >= 10 {
         break
      }
   }
}

Golang 提供for-range的方式,可以方便遍历字符串和数组,案例说明如何遍历字符串。

package main

import "fmt"

func main() {
   //方式1:
   var str string = "hello world"
   for i := 0; i < len(str); i++ {
      fmt.Printf("%c\n", str[i])
   }

   //for-range遍历
   str = "asdccc"
   for index, val := range str {
      fmt.Printf("index=%d,var=%c\n", index, val)
   }
}

如果字符串含有中文,传统的对字符串的遍历是按字节遍历的,一个汉字对应三个字节,需要将str 转换为 []rune 切片,对于for-range是按照字符方式编译,有中文不会影响

package main

import "fmt"

func main() {
   var str string = "hello 江涛"
   str2 := []rune(str)
   for i := 0; i < len(str2); i++ {
      fmt.Printf("%c\n", str2[i])
   }
}

Go语言没有while和do…while

多重循环控制

Golang入门_第25张图片

跳转控制语句-break

随机数生成:

package main

import (
   "fmt"
   "math/rand"
   "time"
)

func main() {
   //生成1-100的随机数
   //设置rand的一个种子
   rand.Seed(time.Now().Unix()) //返回一个从1970:01:01的0时0分0秒到现在的秒数
   n := rand.Intn(100) + 1
   fmt.Println(n)

   //随机生成1-100的一个数,直到生成了99这个数,看看你一共用了几次
   var count int = 0
   for {
      rand.Seed(time.Now().UnixNano())
      n := rand.Intn(100) + 1
      fmt.Println(n)
      count++
      if n == 99 {
         break
      }
   }
   fmt.Println(count)
}

注意事项:

break默认跳出最近的for循环

break配合标签使用

Golang入门_第26张图片
label1:
   for {
      rand.Seed(time.Now().UnixNano())
      n := rand.Intn(1000) + 1
      fmt.Println(n)
      count++
      if n == 999 {
         break label1
      }
   }

跳转控制语句-continue

Golang入门_第27张图片

跳转控制语句-goto

Golang入门_第28张图片
package main

import "fmt"

func main() {
	//goto的使用
	fmt.Println("1")
	fmt.Println("2")
	goto label1
	fmt.Println("3")
	fmt.Println("4")
	fmt.Println("5")
label1:
	fmt.Println("6")
	fmt.Println("7")
}

跳转控制语句-return

return跳出函数

你可能感兴趣的:(golang,开发语言,后端)