Golang基础教程
阅读原文时间:2023年07月10日阅读:3

以下使用goland的IDE演示,包含总计的golang基础功能共20个章节

一、go语言结构:

二、go基础语法:

三、变量

四、常量

五、运算符

六、条件语句

七、循环

八、函数

九、变量作用域

十、数组

十一、指针

十二、结构体

十三、切片

十四、范围(Range)

十五、集合

十六、递归

十七、数据类型转换

十八、接口

十九、错误处理

二十、并发

一、go语言结构:

1.运行Hello World!

package main

import "fmt"

func main() {
fmt.Println("Hello World!")
}

查看运行结果:

2.语言结构:

1. 第一行代码 package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。

2. 下一行 import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。

3. 下一行 func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。

4. 下一行 /*…*/ 是注释,在程序执行时将被忽略。单行注释是最常见的注释形式,你可以在任何地方使用以 // 开头的单行注释。多行注释也叫块注释,均已以 /* 开头,并以 */ 结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。

5.下一行 fmt.Println(…) 可以将字符串输出到控制台,并在最后自动增加换行字符 \n。

使用 fmt.Print("hello, world\n") 可以得到相同的结果。

Print 和 Println 这两个函数也支持使用变量,如:fmt.Println(arr)。如果没有特别指定,它们会以默认的打印格式将变量 arr 输出到控制台。

6. 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )。

二、go基础语法:

1.行分隔符:

Println函数会在行末尾自动加上换行符

package main

import "fmt"

func main() {
fmt.Println("Hello World!")
fmt.Println("Println函数会在行末尾自动加上换行符")
}

查看运行结果:

2.注释:

单行注释以//开头,多行注释以 /* 开头,并以 */ 结尾

// 单行注释

/*

我说多行注释1

我说多行注释2

我说多行注释3

*/

3.标识符:

标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

以下是有效的标识符:

mahesh   kumar   abc   move_name   a_123

myname50   _temp   j   a23b9   retVal

以下是无效的标识符:

* 1ab(以数字开头)

* case(Go 语言的关键字)

* a+b(运算符是不允许的)

4.字符串连接:

Go 语言的字符串连接可以通过 + 实现:

import "fmt"

func main() {
fmt.Println("golang"+"python")
}

查看运行结果:

5.关键字:

下面列举了 Go 代码中会使用到的 25 个关键字或保留字:

break default func interface select

case defer go map struct 

chan else goto package switch

const fallthrough if range type

continue for import return var

6.格式化字符串:

// 常用的使用%d 表示整型数字,%s 表示字符串

package main

import "fmt"

func main() {
//fmt.Println("Hello World!")
//fmt.Println("Println函数会在行末尾自动加上换行符")
//fmt.Println("golang" + "python")
var today = "星期六"
var number = 6
fmt.Printf("今天是%s,今天在本周的排号为%d", today, number)
}

查看运行结果:

三、变量

1、申明一个变量值,变量类型,并初始化

(1)两种方式,方式1:使用var声明

package main

func main() {
var str string = "hello"
var num int = 123
println(str, num)
}

查看运行结果:

(2)使用:=声明

package main

func main() {
//var str string = "hello"
//var num int = 123
//println(str, num)
mystr := "very good"
mynum := 345
println(mystr, mynum)

}

查看运行结果:

2、申请变量未初始化,则会给默认值

数值类型初始值0

布尔类型为fasle

字符串为""

其他类型为nil

func main() {
//var str string = "hello"
//var num int = 123
//println(str, num)

//初始值0
var num1 int
fmt.Println("num1初始值为:", num1)
//初始值""
var str1 string
fmt.Println("str1初始值为:", str1)
//布尔类型为 false
var flag bool
fmt.Println("flag初始值为:", flag)
//其他类型为nil
var a *int
var b []int
var c map[string]int
var d chan int
var e func(string) int
var f error
fmt.Println("a,b,c,d,e,f的初始值分别为:", a, b, c, d, e, f)
}

查看运行结果:

3、根据值自行判定变量类型

package main

import (
"fmt"
"reflect"
)

func main() {

var str2 = "hello"
var num2 = 25
var flag2 = true
fmt.Println("str2的类型为:", reflect.TypeOf(str2))
fmt.Println("num2的类型为:", reflect.TypeOf(num2))
fmt.Println("flag2的类型为:", reflect.TypeOf(flag2))
}

查看运行结果:

4、多变量声明:

使用逗号隔开

package main

import "fmt"

func main() {

var str3, str4, str5 string = "hello", "World", "ok"
num3, num4, num5 := 2, 3, 4
fmt.Println(str3, str4, str5)
fmt.Println(num3, num4, num5)

}

查看运行结果:

5、引用类型变量

&可查看引用变量的地址

package main

import "fmt"

func main() {

var a1 = 10
var b1 = "ok"
fmt.Println("a1=", a1)
fmt.Println("b1=", b1)
fmt.Println("a1=", &a1)
fmt.Println("b1=", &b1)
}

查看运行结果:

四、常量

1.常量定义:

常量是一个简单值的标识符,在程序运行时,不会被修改的量,使用const修饰一个常量

package main

func main() {
const a string = "abc" //显示类型定义
const b = "abc" //隐示类型定义
const c, d = "o", "k"
println(a, b, c, d)
}

查看运行结果:

2. 常量还可以用作枚举:

并且常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过

package main

import "unsafe"

func main() {
//const a string = "abc" //显示类型定义
//const b = "abc" //隐示类型定义
//const c, d = "o", "k"
//println(a, b, c, d)
const (
Unknown = 0
Female = 1
Male = 2
)

const (
a = "abc"
b = len(a)
c = unsafe.Sizeof(a) //16个字节,返回string结构体的字符与长度各8个字符相加
)
println(Unknown, Female, Male, a, b, c)
}

查看运行结果:

3.特殊常量iota

iota,特殊常量,可以认为是一个可以被编译器修改的常量。

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

package main

func main() {

const (
a = iota
b
c
)
println(a, b, c)
}

查看运行结果:

package main

import "fmt"

func main() {

//println(a, b, c)
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a, b, c, d, e, f, g, h, i)
}

查看运行结果:

五、运算符

1.算数运算符:

package main

import "fmt"

func main() {
a := 1
b := 2
fmt.Println("a加b等于:", a+b)
fmt.Println("a减b等于:", a-b)
fmt.Println("a剩b等于:", a*b)
fmt.Println("a除b等于:", a/b)
fmt.Println("a除b后取余数等于:", a%b)
a++
fmt.Println("a++后的结果:", a)
b--
fmt.Println("b--后的结果:", b)
}

查看运行结果:

2.关系运算符

关系运算符主要有 =,!=,>,<,>=,<=共6种运算符

package main

import "fmt"

func main() {

var m int = 21
var n int = 10
if m == n {
fmt.Println("第一行返回:a等于b")
} else {
fmt.Println("第一行返回:a不等于b")
}
if m < n { fmt.Println("第二行返回:a小于b") } else { fmt.Println("第二行返回:a不小于b") } if m > n {
fmt.Println("第三行返回:a大于b")
} else {
fmt.Println("第三行返回:a不大于b")
}
m, n = n, m //交换m,n的值
if m <= n { fmt.Println("第四行返回:a小于等于b") } if m >= n {
fmt.Println("第四行返回:a不小于b")
}
}

查看运行结果:

3.逻辑运算符

主要有三种逻辑运算符:

&&:逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。

||:逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。

!:逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。

package main

import "fmt"

func main() {

var a bool = true
var b bool = false
if a && b {
fmt.Printf("第一行 - 条件为 true\n")
} else if a || b {
fmt.Printf("第一行 - 条件为 true\n")
}
a, b = b, a //修改a,b的值,对调
if a && b {
fmt.Printf("第二行 - 条件为 true\n")
} else {
fmt.Printf("第二行 - 条件为 false\n")
}
if !(a && b) {
fmt.Printf("第三行 - 条件为 true\n")
} else {
fmt.Printf("第三行 - 条件为 false\n")
}

}

查看运行结果:

4.位运算符

位运算符对整数在内存中的二进制位进行操作。

 &, |,  ^ ,<<,>>四种位运算方式

package main

import "fmt"

func main() {

var a uint = 60 /* 60 = 0011 1100 */
var b uint = 13 /* 13 = 0000 1101 */
var c uint = 0

c = a & b /* 12 = 0000 1100 */
fmt.Printf("第一行 - c 的值为 %d\n", c)

c = a | b /* 61 = 0011 1101 */
fmt.Printf("第二行 - c 的值为 %d\n", c)

c = a ^ b /* 49 = 0011 0001 */
fmt.Printf("第三行 - c 的值为 %d\n", c)

c = a << 2 /* 240 = 1111 0000 */
fmt.Printf("第四行 - c 的值为 %d\n", c)

c = a >> 2 /* 15 = 0000 1111 */
fmt.Printf("第五行 - c 的值为 %d\n", c)

}

查看运行结果:

5.赋值运算符

赋值符号为=,将一个表达式的值赋给一个左值,结合之前其他的型号的赋值运算符如下:

package main

import "fmt"

func main() {

var a int = 21
var c int

c = a
fmt.Printf("第 1 行 - = 运算符实例,c 值为 = %d\n", c)

c += a
fmt.Printf("第 2 行 - += 运算符实例,c 值为 = %d\n", c)

c -= a
fmt.Printf("第 3 行 - -= 运算符实例,c 值为 = %d\n", c)

c *= a
fmt.Printf("第 4 行 - *= 运算符实例,c 值为 = %d\n", c)

c /= a
fmt.Printf("第 5 行 - /= 运算符实例,c 值为 = %d\n", c)

c = 200

c <<= 2
fmt.Printf("第 6行 - <<= 运算符实例,c 值为 = %d\n", c)

c >>= 2
fmt.Printf("第 7 行 - >>= 运算符实例,c 值为 = %d\n", c)

c &= 2
fmt.Printf("第 8 行 - &= 运算符实例,c 值为 = %d\n", c)

c ^= 2
fmt.Printf("第 9 行 - ^= 运算符实例,c 值为 = %d\n", c)

c |= 2
fmt.Printf("第 10 行 - |= 运算符实例,c 值为 = %d\n", c)
}

查看运行结果:

六、条件语句

1.if else语句:

package main

import "fmt"

func main() {
//if else语句
age := 18
if age < 5 {
fmt.Println("你的age为:", age, ",你太小了无法进入")
} else if age < 18 {
fmt.Println("你的age为:", age, ",你虽然不小了,但是仍然未满18,无法进入")
} else {
fmt.Println("你的age为:", age, ",你已满18岁,可以进入")
}
}

查看运行结果:

2.if嵌套语句

计算可以数字a在0-100内,且是否可以被5整除

package main

import "fmt"

func main() {

a := 100
//if嵌套
if a <= 100 {
fmt.Println("a的值符合条件1:在0~100内,为:", a)
if a%5 == 0 {
fmt.Println("a的值符合条件2:可以被5整除,为:", a)
} else {
fmt.Println("a的值不符合条件2:不可以被5整除,为:", a)

}
} else {
fmt.Println("a的值不符合条件1:非在0~100内,为:", a)

}
}

查看运行结果:

3.switch语句

(1)switch+case语句:

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

witch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case

package main

import "fmt"

func main() {

//3.switch case语句
score := 75
var grade string
switch {
case score < 60: grade = "C" case score >= 60 && score < 80: grade = "B" case score >= 80:
grade = "A"
}
fmt.Println(grade)

}

查看运行结果:

(2)switch+case+fallthrough

使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。

package main

import "fmt"

func main() {

score := 95
var grade string
switch {
case score < 60: grade = "C" fallthrough case false: fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade) case score >= 60 && score < 80: grade = "B" fallthrough case false: fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade) case score >= 80:
grade = "A"
fallthrough
case false:
fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)
}
fmt.Println(grade)
}

查看运行结果:

(3)switch+default:

defalut如果放在哪里是会最后执行

package main

import "fmt"

func main() {

score := 200
var grade string
switch {
default:
grade = "Nothing"
fmt.Printf("你的成绩为%d,并不合法,最终grade为%s", score, grade)
case score < 60: grade = "C" fallthrough case false: fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade) case score >= 60 && score < 80: grade = "B" fallthrough case false: fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade) case score >= 80 && score <= 100:
grade = "A"
fallthrough
case false:
fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)
}

}

查看运行结果:

4.select语句

select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。

select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。

package main

import "fmt"

func main() {

var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("received ", i1, " from c1\n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
fmt.Printf("received ", i3, " from c3\n")
} else {
fmt.Printf("c3 is closed\n")
}
default:
fmt.Printf("no communication\n")
}

}

查看运行结果:

七、循环

1.for循环

(1)for condition {}

package main

import "fmt"

func main() {
//1.for condition语句
sum := 0
for i := 1; i <= 10; i++ {
sum += i
}
fmt.Println(sum) //累加1~10
}

查看运行结果:

(2)for init {}

package main

import "fmt"

func main() {

Strings := []string{"google", "golang"}
for m, n := range Strings {
fmt.Println(m, n)
}
}

查看运行结果:

2.循环嵌套

package main

import "fmt"

func main() {

//2.循环嵌套:找到1-30内的素数
var i, j int
for i = 2; i < 30; i++ { for j = 2; j <= i/j; j++ { if i%j == 0 { break } } if j > (i / j) {
fmt.Println(i, "是一个素数")
}
}
}

查看运行结果:

3.break语句

Go 语言中 break 语句用于以下两方面:

(1) 用于循环语句中跳出循环,并开始执行循环之后的语句

//3.1 break跳出循环
var a int = 10
for a < 20 {
fmt.Println("a的值:", a)
a++
if a == 15 {
break
}
}
}

查看运行结果:

(2) break 在 switch(开关语句)中在执行一条 case 后跳出语句的作用。(此break会隐藏)

(3)在多重循环中,可以用标号 label 标出想 break 的循环。

package main

import "fmt"

func main() {

//3.2 break label标出想break的循环
// 不使用标记
fmt.Println("---- break ----")
for i := 1; i <= 3; i++ {
fmt.Printf("i: %d\n", i)
for i2 := 11; i2 <= 13; i2++ {
fmt.Printf("i2: %d\n", i2)
break
}
}

// 使用标记
fmt.Println("---- break label ----")
re:
for i := 1; i <= 3; i++ {
fmt.Printf("i: %d\n", i)
for i2 := 11; i2 <= 13; i2++ {
fmt.Printf("i2: %d\n", i2)
break re
}
}

}

查看运行结果:

4.continue 语句

Go 语言的 continue 语句 有点像 break 语句。但是 continue 不是跳出循环,而是跳过当前循环执行下一次循环语句。

(1)for 循环中,执行 continue 语句会触发 for 增量语句的执行。

package main

import "fmt"

func main() {

//4.1 continue语句,不是跳出循环,而是跳过当前循环执行下一次循环语句
a := 10
for a < 20 {
a++
if a == 15 {
continue
}
fmt.Println("a的值为:", a)
}

}

查看运行结果:

(2)在多重循环中,可以用标号 label 标出想 continue 的循环。

package main

import "fmt"

func main() {

//4.2 使用continue+label标出想 continue 的循环
// 不使用标记
fmt.Println("---- continue ---- ")
for i := 1; i <= 3; i++ {
fmt.Printf("i: %d\n", i)
for i2 := 11; i2 <= 13; i2++ {
fmt.Printf("i2: %d\n", i2)
continue
}
}

// 使用标记
fmt.Println("---- continue label ----")
re:
for i := 1; i <= 3; i++ {
fmt.Printf("i: %d\n", i)
for i2 := 11; i2 <= 13; i2++ {
fmt.Printf("i2: %d\n", i2)
continue re
}
}

}

查看运行结果:

5.goto 语句

Go 语言的 goto 语句可以无条件地转移到过程中指定的行。

goto 语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。

package main

import "fmt"

func main() {

//5.goto语句可以无条件地转移到过程中指定的行
/* 定义局部变量 */
var a int = 10

/* 循环 */
LOOP:
for a < 20 {
if a == 15 {
/* 跳过迭代 */
a = a + 1
goto LOOP
}
fmt.Printf("a的值为 : %d\n", a)
a++
}
}

查看运行结果:

八、函数

1.函数定义与调用

Go 语言最少有个 main() 函数。

你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。

函数定义解析:

* func:函数由 func 开始声明

* function_name:函数名称,参数列表和返回值类型构成了函数签名。

* parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。

* return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。

* 函数体:函数定义的代码集合。

package main

import "fmt"

func main() {
var a int = 98
var b int = 99
var c int = max(a, b)
fmt.Println("a,b两个数的最大值为:", c)
}

func max(num1, num2 int) int {
/* 声明局部变量 */
var result int

if num1 > num2 {
result = num1
} else {
result = num2
}
return result
}

查看运行结果:

2.函数返回多个值

package main

import "fmt"

func main() {

x := "hello"
y := "world"
fmt.Println("交换前的x与y分别为:", x, y)
x, y = swap(x, y)
fmt.Println("交换后的x与y分别为:", x, y)
}

func swap(x, y string) (string, string) {
x, y = y, x
return x, y
}

查看运行结果:

3.值传递与引用传递

(1)值传递:

值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

package main

import (
"fmt"
)

func main() {

x := "hello"
y := "world"
fmt.Println("交换前的x与y分别为:", x, y)
swap(x, y)
fmt.Println("交换后的x与y分别为:", x, y)
}

//值传递
func swap(x, y string) string {
var temp string
temp = x
x = y
y = temp
return temp
}

查看运行结果:

(2)引用传递:

引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

package main

import (
"fmt"
)

func main() {
//var a int = 98
//var b int = 99
//var c int = max(a, b)
//fmt.Println("a,b两个数的最大值为:", c)

x := "hello"
y := "world"
fmt.Println("交换前的x与y分别为:", x, y)
swap(&x, &y)
fmt.Println("交换后的x与y分别为:", x, y)
}

//func max(num1, num2 int) int {
// /* 声明局部变量 */
// var result int
//
// if num1 > num2 {
// result = num1
// } else {
// result = num2
// }
// return result
//}

////值传递
//func swap(x, y string) string {
// var temp string
// temp = x
// x = y
// y = temp
// return temp
//}

//引用传递
func swap(x, y *string) string {
var temp string
temp = *x
*x = *y
*y = temp
return temp
}

查看运行结果:

4.函数作为另外一个函数的实参(进阶ToDo)

5.闭包(进阶ToDo)

6.方法(进阶ToDo)

九、变量作用域

1.局部变量:

* 函数内定义的变量称为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

package main

import "fmt"

func main() {
/* 声明局部变量 */
var a, b, c int

/* 初始化参数 */
a = 10
b = 20
c = a + b

fmt.Printf("结果: a = %d, b = %d and c = %d\n", a, b, c)
}

查看运行结果:

2.全局变量

* 函数外定义的变量称为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用

package main

import "fmt"

/* 声明全局变量 */
var g int

func main() {

/* 声明局部变量 */
var a, b int

/* 初始化参数 */
a = 10
b = 20
g = a + b

fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)
}

查看运行结果:

3.形式参数

形式参数会作为函数的局部变量来使用。实例如下:

package main

import "fmt"

///* 声明全局变量 */
//var g int

/* 声明全局变量 */
var a int = 20

func main() {

/* main 函数中声明局部变量 */
var a int = 10
var b int = 20
var c int = 0

fmt.Printf("main()函数中 a = %d\n", a)
c = sum(a, b)
fmt.Printf("main()函数中 c = %d\n", c)
}

/* 函数定义-两数相加 */
func sum(a, b int) int {
fmt.Printf("sum() 函数中 a = %d\n", a)
fmt.Printf("sum() 函数中 b = %d\n", b)

return a + b
}

查看运行结果:

4.初始化局部和全局变量

不同类型的局部和全局变量的默认值为:

int为0

float32为0

pointer为nil

十、数组

1.声明数组

例如以下定义了数组 balance 长度为 10 类型为 float32:

var balance [10] float32

2.初始化数组

package main

import "fmt"

func main() {
//1.初始化数组
balance1 := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
fmt.Println(balance1)
//如果数组长度不确定,可以使用 … 代替数组的长度,编译器会根据元素个数自行推断数组的长度:
balance2 := […]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
fmt.Println(balance2)
}

查看运行结果:

3.访问数组元素

package main

import "fmt"

func main() {

//3.访问列表元素,通过for循环方式遍历
var n [10]int /* n 是一个长度为 10 的数组 */
var i, j int

/* 为数组 n 初始化元素 */
for i = 0; i < 10; i++ {
n[i] = i + 100 /* 设置元素为 i + 100 */
}

/* 输出每个数组元素的值 */
for j = 0; j < 10; j++ {
fmt.Printf("Element[%d] = %d\n", j, n[j])
}
}

查看运行结果:

4.多维数组(进阶ToDo)

5.向函数传递数组(进阶ToDo)

十一、指针

1.指针的使用

一个指针变量指向了一个值的内存地址。

var ip *int        /* 指向整型*/

var fp *float32    /* 指向浮点型 */

package main

import "fmt"

func main() {
var a int = 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */

ip = &a /* 指针变量的存储地址 */

fmt.Printf("a 变量的地址是: %x\n", &a)

/* 指针变量的存储地址 */
fmt.Printf("ip 变量储存的指针地址: %x\n", ip)

/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *ip)
}

查看运行结果:

2.空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil。

nil 指针也称为空指针。

nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

一个指针变量通常缩写为 ptr。

package main

import "fmt"

func main() {

//空指针
var ptr *int
fmt.Printf("ptr 的值为 : %x\n", ptr)
}

查看运行结果:

3.指针数组(进阶ToDo)

4.指向指针的指针(进阶ToDo)

5.指针作为函数参数(进阶ToDo)

十二、结构体

1.定义结构体

Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。

package main

import "fmt"

//定义结构体
type Books struct {
title string
author string
subject string
bookId int
}

func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "mr.white", "Go语言教程", 100001})

// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "mr.white", subject: "Go语言教程", bookId: 100002})

// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "mr.white"})
}

查看运行结果:

2.访问结构体成员

如果要访问结构体成员,需要使用点号 . 操作符。

package main

import "fmt"

//定义结构体
type Books struct {
title string
author string
subject string
bookId int
}

func main() {

/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "mr.white"
Book1.subject = "Go 语言教程"
Book1.bookId = 100001

/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "mr.white"
Book2.subject = "Python 语言教程"
Book2.bookId = 100002

/* 打印 Book1 信息 */
fmt.Printf("Book 1 title : %s\n", Book1.title)
fmt.Printf("Book 1 author : %s\n", Book1.author)
fmt.Printf("Book 1 subject : %s\n", Book1.subject)
fmt.Printf("Book 1 book_id : %d\n", Book1.bookId)

/* 打印 Book2 信息 */
fmt.Printf("Book 2 title : %s\n", Book2.title)
fmt.Printf("Book 2 author : %s\n", Book2.author)
fmt.Printf("Book 2 subject : %s\n", Book2.subject)
fmt.Printf("Book 2 book_id : %d\n", Book2.bookId)
}

查看运行结果:

3.结构体作为函数参数(进阶ToDo)

4.结构体指针(进阶ToDo)

十三、切片

1.定义/切片初始化

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

package main

import "fmt"

func main() {
//1.直接初始化切片,[] 表示是切片类型,{1,2,3} 初始化值依次是 1,2,3,其 cap=len=3。
s := []int{1, 2, 3}
fmt.Println("切片s:", s)
//初始化切片 s1,是数组 s 的引用。
s1 := s[:]
fmt.Println("切片s1:", s1)
//初始化切片 s2,是从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片。
s2 := s[1:3]
fmt.Println("切片s2:", s2)
//使用make初始化切片
s3 := make([]int, 3)
fmt.Println("切片s3:", s3)
}

查看运行结果:

2.len() 和 cap() 函数

len() 方法获取切片的长度

cap()方法 可以测量切片最长可以达到多少

package main

import "fmt"

func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {

//2调用printSlice方法获取切片的长度与容量
var numbers = make([]int, 3, 5)
printSlice(numbers)
}

查看运行结果:

3.空(nil)切片

package main

import "fmt"

func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {

//3.空切片
var numbers []int
printSlice(numbers)
if numbers == nil {
fmt.Println("切片是空的呢")
}
}

查看运行结果:

6.切片截取

可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound],实例如下:

package main

import "fmt"

func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {

//切片截取举例
/* 创建切片 */
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
printSlice(numbers)

/* 打印原始切片 */
fmt.Println("numbers ==", numbers)

/* 打印子切片从索引1(包含) 到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4])

/* 默认下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3])

/* 默认上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:])

numbers1 := make([]int, 0, 5)
printSlice(numbers1)

/* 打印子切片从索引 0(包含) 到索引 2(不包含) */
number2 := numbers[:2]
printSlice(number2)

/* 打印子切片从索引 2(包含) 到索引 5(不包含) */
number3 := numbers[2:5]
printSlice(number3)
}

查看运行结果:

7.append() 和 copy() 函数

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。

package main

import "fmt"

func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

func main() {

//5.append() 和 copy() 函数
var numbers []int
printSlice(numbers)

/* 允许追加空切片 */
numbers = append(numbers, 0)
printSlice(numbers)

/* 向切片添加一个元素 */
numbers = append(numbers, 1)
printSlice(numbers)

/* 同时添加多个元素 */
numbers = append(numbers, 2,3,4)
printSlice(numbers)

/* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)

/* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1,numbers)
printSlice(numbers1)
}

查看运行结果:

十四、范围(Range)

1.range的作用

range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环

2.举例说明

package main

import "fmt"

func main() {
map1 := make(map[int]float32)
map1[1] = 1.0
map1[2] = 2.0
map1[3] = 3.0
map1[4] = 4.0

// 读取 key 和 value
for key, value := range map1 {
fmt.Printf("key is: %d - value is: %f\n", key, value)
}

// 读取 key
for key := range map1 {
fmt.Printf("key is: %d\n", key)
}

// 读取 value
for _, value := range map1 {
fmt.Printf("value is: %f\n", value)
}
}

查看运行结果:

十五、集合

1.定义 Map

/* 声明变量,默认 map 是 nil */

var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */

map_variable := make(map[key_data_type]value_data_type)

实例如下:

package main

import "fmt"

func main() {
var countryCapitalMap map[string]string /*创建集合 */
countryCapitalMap = make(map[string]string)

/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap["France"] = "巴黎"
countryCapitalMap["Italy"] = "罗马"
countryCapitalMap["Japan"] = "东京"
countryCapitalMap["India "] = "新德里"

/*使用键输出地图值 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap[country])
}

/*查看元素在集合中是否存在 */
capital, ok := countryCapitalMap["American"] /*如果确定是真实的,则存在,否则不存在 */
/*fmt.Println(capital) */
/*fmt.Println(ok) */
if ok {
fmt.Println("American 的首都是", capital)
} else {
fmt.Println("American 的首都不存在")
}
}

查看运行结果:

2.delete() 函数

delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。实例如下:

package main

import "fmt"

func main() {
//2.delete() 函数
/* 创建map */
countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}

fmt.Println("原始地图")

/* 打印地图 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap[country])
}

/*删除元素*/
delete(countryCapitalMap, "France")
fmt.Println("法国条目被删除")

fmt.Println("删除元素后地图")

/*打印地图*/
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap[country])
}
}

查看运行结果:

十六、递归

Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。

递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等

1.阶乘

package main

import "fmt"

func Factorial(n uint64) (result uint64) {
if n > 0 {
result = n * Factorial(n-1)
return result
}
return 1
}

func main() {
//1.阶乘
var i int = 15
fmt.Printf("%d 的阶乘是 %d\n", i, Factorial(uint64(i)))
}

查看运行结果:

2.斐波那契数列

package main

import "fmt"

func fibonacci(n int) int {
if n < 2 {
return n
}
return fibonacci(n-2) + fibonacci(n-1)
}

func main() {

//2.斐波那契数列
var i int
for i = 0; i < 10; i++ {
fmt.Printf("%d\t", fibonacci(i))
}
}

查看运行结果:

十七、数据类型转换

1.转换规则

类型转换用于将一种数据类型的变量转换为另外一种类型的变量。Go 语言类型转换基本格式如下:

type_name(expression)

2.实例

package main

import "fmt"

func main() {
var sum int = 17
var count int = 5
var mean float32

mean = float32(sum)/float32(count)
fmt.Printf("mean 的值为: %f\n",mean)
}

查看运行结果:

十八、接口

1.接口含义

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

2.实例

package main

import "fmt"

type Phone interface {
/* 定义结构体 */
call()
}

type NokiaPhone struct {
/* 定义结构体 */
}

func (nokiaPhone NokiaPhone) call() {
/* 实现接口方法 */
fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
/* 定义结构体 */
}

func (iPhone IPhone) call() {
/* 实现接口方法 */
fmt.Println("I am iPhone, I can call you!")
}

func main() {
var phone Phone

phone = new(NokiaPhone)
phone.call()

phone = new(IPhone)
phone.call()
}

查看运行结果:

十九、错误处理

1.error简介

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

type error interface {
Error() string}

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("math: square root of negative number")
}

// 实现}

在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:

result, err:= Sqrt(-1)

if err != nil {
fmt.Println(err)
}

2.实例

package main

import "fmt"

// 定义一个 DivideError 结构
type DivideError struct {
dividee int
divider int
}

// 实现 `error` 接口
func (de *DivideError) Error() string {
strFormat := `
Cannot proceed, the divider is zero.
dividee: %d
divider: 0
`
return fmt.Sprintf(strFormat, de.dividee)
}

// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
if varDivider == 0 {
dData := DivideError{
dividee: varDividee,
divider: varDivider,
}
errorMsg = dData.Error()
return
} else {
return varDividee / varDivider, ""
}

}

func main() {
// 正常情况
if result, errorMsg := Divide(100, 10); errorMsg == "" {
fmt.Println("100/10 = ", result)
}
// 当除数为零的时候会返回错误信息
if _, errorMsg := Divide(100, 0); errorMsg != "" {
fmt.Println("errorMsg is: ", errorMsg)
}
}

查看运行结果:

二十、并发

1.并发介绍

Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

语句:go f(x, y, z)

如:开启一个新的 goroutine:

f(x, y, z)

2.实例

package main

import (
"fmt"
"time"
)

func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}

func main() {
go say("world")
say("hello")
}

查看运行结果:

以下使用goland的IDE演示,包含总计的golang基础功能共20个章节

一、go语言结构:

二、go基础语法:

三、变量

四、常量

一、go语言结构:

1.运行Hello World!

package main

import "fmt"

func main() {

fmt.Println("Hello World!")

}

查看运行结果:

2.语言结构:

1. 第一行代码 package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。

2. 下一行 import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。

3. 下一行 func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。

4. 下一行 /*…*/ 是注释,在程序执行时将被忽略。单行注释是最常见的注释形式,你可以在任何地方使用以 // 开头的单行注释。多行注释也叫块注释,均已以 /* 开头,并以 */ 结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。

5.下一行 fmt.Println(…) 可以将字符串输出到控制台,并在最后自动增加换行字符 \n。

使用 fmt.Print("hello, world\n") 可以得到相同的结果。

Print 和 Println 这两个函数也支持使用变量,如:fmt.Println(arr)。如果没有特别指定,它们会以默认的打印格式将变量 arr 输出到控制台。

6. 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )。

二、go基础语法:

1.行分隔符:

Println函数会在行末尾自动加上换行符

package main

import "fmt"

func main() {

fmt.Println("Hello World!")

fmt.Println("Println函数会在行末尾自动加上换行符")

}

查看运行结果:

2.注释:

单行注释以//开头,多行注释以 /* 开头,并以 */ 结尾

// 单行注释

/*

我说多行注释1

我说多行注释2

我说多行注释3

*/

3.标识符:

标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

以下是有效的标识符:

mahesh   kumar   abc   move_name   a_123

myname50   _temp   j   a23b9   retVal

以下是无效的标识符:

* 1ab(以数字开头)

* case(Go 语言的关键字)

* a+b(运算符是不允许的)

4.字符串连接:

Go 语言的字符串连接可以通过 + 实现:

import "fmt"

func main() {

fmt.Println("golang"+"python")

}

查看运行结果:

5.关键字:

下面列举了 Go 代码中会使用到的 25 个关键字或保留字:

break default func interface select

case defer go map struct 

chan else goto package switch

const fallthrough if range type

continue for import return var

6.格式化字符串:

// 常用的使用%d 表示整型数字,%s 表示字符串

package main

import "fmt"

func main() {

//fmt.Println("Hello World!")

//fmt.Println("Println函数会在行末尾自动加上换行符")

//fmt.Println("golang" + "python")

var today = "星期六"

var number = 6

fmt.Printf("今天是%s,今天在本周的排号为%d", today, number)

}

查看运行结果:

三、变量

1、申明一个变量值,变量类型,并初始化

(1)两种方式,方式1:使用var声明

package main

func main() {

var str string = "hello"

var num int = 123

println(str, num)

}

查看运行结果:

(2)使用:=声明

package main

func main() {

//var str string = "hello"

//var num int = 123

//println(str, num)

mystr := "very good"

mynum := 345

println(mystr, mynum)

}

查看运行结果:

2、申请变量未初始化,则会给默认值

数值类型初始值0

布尔类型为fasle

字符串为""

其他类型为nil

func main() {

//var str string = "hello"

//var num int = 123

//println(str, num)

//初始值0

var num1 int

fmt.Println("num1初始值为:", num1)

//初始值""

var str1 string

fmt.Println("str1初始值为:", str1)

//布尔类型为 false

var flag bool

fmt.Println("flag初始值为:", flag)

//其他类型为nil

var a *int

var b []int

var c map[string]int

var d chan int

var e func(string) int

var f error

fmt.Println("a,b,c,d,e,f的初始值分别为:", a, b, c, d, e, f)

}

查看运行结果:

3、根据值自行判定变量类型

package main

import (

"fmt"

"reflect"

)

func main() {

var str2 = "hello"

var num2 = 25

var flag2 = true

fmt.Println("str2的类型为:", reflect.TypeOf(str2))

fmt.Println("num2的类型为:", reflect.TypeOf(num2))

fmt.Println("flag2的类型为:", reflect.TypeOf(flag2))

}

查看运行结果:

4、多变量声明:

使用逗号隔开

package main

import "fmt"

func main() {

var str3, str4, str5 string = "hello", "World", "ok"

num3, num4, num5 := 2, 3, 4

fmt.Println(str3, str4, str5)

fmt.Println(num3, num4, num5)

}

查看运行结果:

5、引用类型变量

&可查看引用变量的地址

package main

import "fmt"

func main() {

var a1 = 10

var b1 = "ok"

fmt.Println("a1=", a1)

fmt.Println("b1=", b1)

fmt.Println("a1=", &a1)

fmt.Println("b1=", &b1)

}

查看运行结果:

四、常量

1.常量定义:

常量是一个简单值的标识符,在程序运行时,不会被修改的量,使用const修饰一个常量

package main

func main() {

const a string = "abc" //显示类型定义

const b = "abc" //隐示类型定义

const c, d = "o", "k"

println(a, b, c, d)

}

查看运行结果:

2. 常量还可以用作枚举:

并且常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过

package main

import "unsafe"

func main() {

//const a string = "abc" //显示类型定义

//const b = "abc" //隐示类型定义

//const c, d = "o", "k"

//println(a, b, c, d)

const (

Unknown = 0

Female = 1

Male = 2

)

const (

a = "abc"

b = len(a)

c = unsafe.Sizeof(a) //16个字节,返回string结构体的字符与长度各8个字符相加

)

println(Unknown, Female, Male, a, b, c)

}

查看运行结果:

3.特殊常量iota

iota,特殊常量,可以认为是一个可以被编译器修改的常量。

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

package main

func main() {

const (

a = iota

b

c

)

println(a, b, c)

}

查看运行结果:

package main

import "fmt"

func main() {

//println(a, b, c)

const (

a = iota //0

b //1

c //2

d = "ha" //独立值,iota += 1

e //"ha" iota += 1

f = 100 //iota +=1

g //100 iota +=1

h = iota //7,恢复计数

i //8

)

fmt.Println(a, b, c, d, e, f, g, h, i)

}

查看运行结果:

五、运算符

1.算数运算符:

package main

import "fmt"

func main() {

a := 1

b := 2

fmt.Println("a加b等于:", a+b)

fmt.Println("a减b等于:", a-b)

fmt.Println("a剩b等于:", a*b)

fmt.Println("a除b等于:", a/b)

fmt.Println("a除b后取余数等于:", a%b)

a++

fmt.Println("a++后的结果:", a)

b--

fmt.Println("b--后的结果:", b)

}

查看运行结果:

2.关系运算符

关系运算符主要有 =,!=,>,<,>=,<=共6种运算符

package main

import "fmt"

func main() {

var m int = 21

var n int = 10

if m == n {

fmt.Println("第一行返回:a等于b")

} else {

fmt.Println("第一行返回:a不等于b")

}

if m < n {

fmt.Println("第二行返回:a小于b")

} else {

fmt.Println("第二行返回:a不小于b")

}

if m > n {

fmt.Println("第三行返回:a大于b")

} else {

fmt.Println("第三行返回:a不大于b")

}

m, n = n, m //交换m,n的值

if m <= n {

fmt.Println("第四行返回:a小于等于b")

}

if m >= n {

fmt.Println("第四行返回:a不小于b")

}

}

查看运行结果:

3.逻辑运算符

主要有三种逻辑运算符:

&&:逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。

||:逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。

!:逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。

package main

import "fmt"

func main() {

var a bool = true

var b bool = false

if a && b {

fmt.Printf("第一行 - 条件为 true\n")

} else if a || b {

fmt.Printf("第一行 - 条件为 true\n")

}

a, b = b, a //修改a,b的值,对调

if a && b {

fmt.Printf("第二行 - 条件为 true\n")

} else {

fmt.Printf("第二行 - 条件为 false\n")

}

if !(a && b) {

fmt.Printf("第三行 - 条件为 true\n")

} else {

fmt.Printf("第三行 - 条件为 false\n")

}

}

查看运行结果:

4.位运算符

位运算符对整数在内存中的二进制位进行操作。

 &, |,  ^ ,<<,>>四种位运算方式

package main

import "fmt"

func main() {

var a uint = 60 /* 60 = 0011 1100 */

var b uint = 13 /* 13 = 0000 1101 */

var c uint = 0

c = a & b /* 12 = 0000 1100 */

fmt.Printf("第一行 - c 的值为 %d\n", c)

c = a | b /* 61 = 0011 1101 */

fmt.Printf("第二行 - c 的值为 %d\n", c)

c = a ^ b /* 49 = 0011 0001 */

fmt.Printf("第三行 - c 的值为 %d\n", c)

c = a << 2 /* 240 = 1111 0000 */

fmt.Printf("第四行 - c 的值为 %d\n", c)

c = a >> 2 /* 15 = 0000 1111 */

fmt.Printf("第五行 - c 的值为 %d\n", c)

}

查看运行结果:

5.赋值运算符

赋值符号为=,将一个表达式的值赋给一个左值,结合之前其他的型号的赋值运算符如下:

package main

import "fmt"

func main() {

var a int = 21

var c int

c = a

fmt.Printf("第 1 行 - = 运算符实例,c 值为 = %d\n", c)

c += a

fmt.Printf("第 2 行 - += 运算符实例,c 值为 = %d\n", c)

c -= a

fmt.Printf("第 3 行 - -= 运算符实例,c 值为 = %d\n", c)

c *= a

fmt.Printf("第 4 行 - *= 运算符实例,c 值为 = %d\n", c)

c /= a

fmt.Printf("第 5 行 - /= 运算符实例,c 值为 = %d\n", c)

c = 200

c <<= 2

fmt.Printf("第 6行 - <<= 运算符实例,c 值为 = %d\n", c)

c >>= 2

fmt.Printf("第 7 行 - >>= 运算符实例,c 值为 = %d\n", c)

c &= 2

fmt.Printf("第 8 行 - &= 运算符实例,c 值为 = %d\n", c)

c ^= 2

fmt.Printf("第 9 行 - ^= 运算符实例,c 值为 = %d\n", c)

c |= 2

fmt.Printf("第 10 行 - |= 运算符实例,c 值为 = %d\n", c)

}

查看运行结果:

六、条件语句

1.if else语句:

package main

import "fmt"

func main() {

//if else语句

age := 18

if age < 5 {

fmt.Println("你的age为:", age, ",你太小了无法进入")

} else if age < 18 {

fmt.Println("你的age为:", age, ",你虽然不小了,但是仍然未满18,无法进入")

} else {

fmt.Println("你的age为:", age, ",你已满18岁,可以进入")

}

}

查看运行结果:

2.if嵌套语句

计算可以数字a在0-100内,且是否可以被5整除

package main

import "fmt"

func main() {

a := 100

//if嵌套

if a <= 100 {

fmt.Println("a的值符合条件1:在0~100内,为:", a)

if a%5 == 0 {

fmt.Println("a的值符合条件2:可以被5整除,为:", a)

} else {

fmt.Println("a的值不符合条件2:不可以被5整除,为:", a)

}

} else {

fmt.Println("a的值不符合条件1:非在0~100内,为:", a)

}

}

查看运行结果:

3.switch语句

(1)switch+case语句:

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

witch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case

package main

import "fmt"

func main() {

//3.switch case语句

score := 75

var grade string

switch {

case score < 60:

grade = "C"

case score >= 60 && score < 80:

grade = "B"

case score >= 80:

grade = "A"

}

fmt.Println(grade)

}

查看运行结果:

(2)switch+case+fallthrough

使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。

package main

import "fmt"

func main() {

score := 95

var grade string

switch {

case score < 60:

grade = "C"

fallthrough

case false:

fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)

case score >= 60 && score < 80:

grade = "B"

fallthrough

case false:

fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)

case score >= 80:

grade = "A"

fallthrough

case false:

fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)

}

fmt.Println(grade)

}

查看运行结果:

(3)switch+default:

defalut如果放在哪里是会最后执行

package main

import "fmt"

func main() {

score := 200

var grade string

switch {

default:

grade = "Nothing"

fmt.Printf("你的成绩为%d,并不合法,最终grade为%s", score, grade)

case score < 60:

grade = "C"

fallthrough

case false:

fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)

case score >= 60 && score < 80:

grade = "B"

fallthrough

case false:

fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)

case score >= 80 && score <= 100:

grade = "A"

fallthrough

case false:

fmt.Println("使用fallthrough语句跳入到了下一步打印此句,因为您的成绩为:", grade)

}

}

查看运行结果:

4.select语句

select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。

select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。

package main

import "fmt"

func main() {

var c1, c2, c3 chan int

var i1, i2 int

select {

case i1 = <-c1:

fmt.Printf("received ", i1, " from c1\n")

case c2 <- i2:

fmt.Printf("sent ", i2, " to c2\n")

case i3, ok := (<-c3): // same as: i3, ok := <-c3

if ok {

fmt.Printf("received ", i3, " from c3\n")

} else {

fmt.Printf("c3 is closed\n")

}

default:

fmt.Printf("no communication\n")

}

}

查看运行结果:

七、循环

1.for循环

(1)for condition {}

package main

import "fmt"

func main() {

//1.for condition语句

sum := 0

for i := 1; i <= 10; i++ {

sum += i

}

fmt.Println(sum) //累加1~10

}

查看运行结果:

(2)for init {}

package main

import "fmt"

func main() {

Strings := []string{"google", "golang"}

for m, n := range Strings {

fmt.Println(m, n)

}

}

查看运行结果:

2.循环嵌套

package main

import "fmt"

func main() {

//2.循环嵌套:找到1-30内的素数

var i, j int

for i = 2; i < 30; i++ {

for j = 2; j <= i/j; j++ {

if i%j == 0 {

break

}

}

if j > (i / j) {

fmt.Println(i, "是一个素数")

}

}

}

查看运行结果:

3.break语句

Go 语言中 break 语句用于以下两方面:

(1) 用于循环语句中跳出循环,并开始执行循环之后的语句。

//3.1 break跳出循环

var a int = 10

for a < 20 {

fmt.Println("a的值:", a)

a++

if a == 15 {

break

}

}

}

查看运行结果:

(2) break 在 switch(开关语句)中在执行一条 case 后跳出语句的作用。(此break会隐藏)

(3)在多重循环中,可以用标号 label 标出想 break 的循环。

package main

import "fmt"

func main() {

//3.2 break label标出想break的循环

// 不使用标记

fmt.Println("---- break ----")

for i := 1; i <= 3; i++ {

fmt.Printf("i: %d\n", i)

for i2 := 11; i2 <= 13; i2++ {

fmt.Printf("i2: %d\n", i2)

break

}

}

// 使用标记

fmt.Println("---- break label ----")

re:

for i := 1; i <= 3; i++ {

fmt.Printf("i: %d\n", i)

for i2 := 11; i2 <= 13; i2++ {

fmt.Printf("i2: %d\n", i2)

break re

}

}

}

查看运行结果:

4.continue 语句

Go 语言的 continue 语句 有点像 break 语句。但是 continue 不是跳出循环,而是跳过当前循环执行下一次循环语句。

(1)for 循环中,执行 continue 语句会触发 for 增量语句的执行。

package main

import "fmt"

func main() {

//4.1 continue语句,不是跳出循环,而是跳过当前循环执行下一次循环语句

a := 10

for a < 20 {

a++

if a == 15 {

continue

}

fmt.Println("a的值为:", a)

}

}

查看运行结果:

(2)在多重循环中,可以用标号 label 标出想 continue 的循环。

package main

import "fmt"

func main() {

//4.2 使用continue+label标出想 continue 的循环

// 不使用标记

fmt.Println("---- continue ---- ")

for i := 1; i <= 3; i++ {

fmt.Printf("i: %d\n", i)

for i2 := 11; i2 <= 13; i2++ {

fmt.Printf("i2: %d\n", i2)

continue

}

}

// 使用标记

fmt.Println("---- continue label ----")

re:

for i := 1; i <= 3; i++ {

fmt.Printf("i: %d\n", i)

for i2 := 11; i2 <= 13; i2++ {

fmt.Printf("i2: %d\n", i2)

continue re

}

}

}

查看运行结果:

5.goto 语句

Go 语言的 goto 语句可以无条件地转移到过程中指定的行。

goto 语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。

package main

import "fmt"

func main() {

//5.goto语句可以无条件地转移到过程中指定的行

/* 定义局部变量 */

var a int = 10

/* 循环 */

LOOP:

for a < 20 {

if a == 15 {

/* 跳过迭代 */

a = a + 1

goto LOOP

}

fmt.Printf("a的值为 : %d\n", a)

a++

}

}

查看运行结果:

八、函数

1.函数定义与调用

Go 语言最少有个 main() 函数。

你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。

函数定义解析:

* func:函数由 func 开始声明

* function_name:函数名称,参数列表和返回值类型构成了函数签名。

* parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。

* return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。

* 函数体:函数定义的代码集合。

package main

import "fmt"

func main() {

var a int = 98

var b int = 99

var c int = max(a, b)

fmt.Println("a,b两个数的最大值为:", c)

}

func max(num1, num2 int) int {

/* 声明局部变量 */

var result int

if num1 > num2 {

result = num1

} else {

result = num2

}

return result

}

查看运行结果:

2.函数返回多个值

package main

import "fmt"

func main() {

x := "hello"

y := "world"

fmt.Println("交换前的x与y分别为:", x, y)

x, y = swap(x, y)

fmt.Println("交换后的x与y分别为:", x, y)

}

func swap(x, y string) (string, string) {

x, y = y, x

return x, y

}

查看运行结果:

3.值传递与引用传递

(1)值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

package main

import (

"fmt"

)

func main() {

x := "hello"

y := "world"

fmt.Println("交换前的x与y分别为:", x, y)

swap(x, y)

fmt.Println("交换后的x与y分别为:", x, y)

}

//值传递

func swap(x, y string) string {

var temp string

temp = x

x = y

y = temp

return temp

}

查看运行结果:

(2)引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

package main

import (

"fmt"

)

func main() {

//var a int = 98

//var b int = 99

//var c int = max(a, b)

//fmt.Println("a,b两个数的最大值为:", c)

x := "hello"

y := "world"

fmt.Println("交换前的x与y分别为:", x, y)

swap(&x, &y)

fmt.Println("交换后的x与y分别为:", x, y)

}

//func max(num1, num2 int) int {

// /* 声明局部变量 */

// var result int

//

// if num1 > num2 {

// result = num1

// } else {

// result = num2

// }

// return result

//}

////值传递

//func swap(x, y string) string {

// var temp string

// temp = x

// x = y

// y = temp

// return temp

//}

//引用传递

func swap(x, y *string) string {

var temp string

temp = *x

*x = *y

*y = temp

return temp

}

查看运行结果:

4.函数作为另外一个函数的实参(进阶ToDo)

5.闭包(进阶ToDo)

6.方法(进阶ToDo)

九、变量作用域

1.局部变量:

* 函数内定义的变量称为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

package main

import "fmt"

func main() {

/* 声明局部变量 */

var a, b, c int

/* 初始化参数 */

a = 10

b = 20

c = a + b

fmt.Printf("结果: a = %d, b = %d and c = %d\n", a, b, c)

}

查看运行结果:

2.全局变量

* 函数外定义的变量称为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用

package main

import "fmt"

/* 声明全局变量 */

var g int

func main() {

/* 声明局部变量 */

var a, b int

/* 初始化参数 */

a = 10

b = 20

g = a + b

fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)

}

查看运行结果:

3.形式参数

形式参数会作为函数的局部变量来使用。实例如下:

package main

import "fmt"

///* 声明全局变量 */

//var g int

/* 声明全局变量 */

var a int = 20

func main() {

/* main 函数中声明局部变量 */

var a int = 10

var b int = 20

var c int = 0

fmt.Printf("main()函数中 a = %d\n", a)

c = sum(a, b)

fmt.Printf("main()函数中 c = %d\n", c)

}

/* 函数定义-两数相加 */

func sum(a, b int) int {

fmt.Printf("sum() 函数中 a = %d\n", a)

fmt.Printf("sum() 函数中 b = %d\n", b)

return a + b

}

查看运行结果:

4.初始化局部和全局变量

不同类型的局部和全局变量的默认值为:

int为0

float32为0

pointer为nil

十、数组

1.声明数组

例如以下定义了数组 balance 长度为 10 类型为 float32:

var balance [10] float32

2.初始化数组

package main

import "fmt"

func main() {

//1.初始化数组

balance1 := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

fmt.Println(balance1)

//如果数组长度不确定,可以使用 … 代替数组的长度,编译器会根据元素个数自行推断数组的长度:

balance2 := […]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

fmt.Println(balance2)

}

查看运行结果:

3.访问数组元素

package main

import "fmt"

func main() {

//3.访问列表元素,通过for循环方式遍历

var n [10]int /* n 是一个长度为 10 的数组 */

var i, j int

/* 为数组 n 初始化元素 */

for i = 0; i < 10; i++ {

n[i] = i + 100 /* 设置元素为 i + 100 */

}

/* 输出每个数组元素的值 */

for j = 0; j < 10; j++ {

fmt.Printf("Element[%d] = %d\n", j, n[j])

}

}

查看运行结果:

4.多维数组(进阶ToDo)

5.向函数传递数组(进阶ToDo)

十一、指针

1.指针的使用

一个指针变量指向了一个值的内存地址。

var ip *int        /* 指向整型*/

var fp *float32    /* 指向浮点型 */

package main

import "fmt"

func main() {

var a int = 20 /* 声明实际变量 */

var ip *int /* 声明指针变量 */

ip = &a /* 指针变量的存储地址 */

fmt.Printf("a 变量的地址是: %x\n", &a)

/* 指针变量的存储地址 */

fmt.Printf("ip 变量储存的指针地址: %x\n", ip)

/* 使用指针访问值 */

fmt.Printf("*ip 变量的值: %d\n", *ip)

}

查看运行结果:

2.空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil。

nil 指针也称为空指针。

nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

一个指针变量通常缩写为 ptr。

package main

import "fmt"

func main() {

//空指针

var ptr *int

fmt.Printf("ptr 的值为 : %x\n", ptr)

}

查看运行结果:

3.指针数组(进阶ToDo)

4.指向指针的指针(进阶ToDo)

5.指针作为函数参数(进阶ToDo)

十二、结构体

1.定义结构体

Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。

package main

import "fmt"

//定义结构体

type Books struct {

title string

author string

subject string

bookId int

}

func main() {

// 创建一个新的结构体

fmt.Println(Books{"Go 语言", "mr.white", "Go语言教程", 100001})

// 也可以使用 key => value 格式

fmt.Println(Books{title: "Go 语言", author: "mr.white", subject: "Go语言教程", bookId: 100002})

// 忽略的字段为 0 或 空

fmt.Println(Books{title: "Go 语言", author: "mr.white"})

}

查看运行结果:

2.访问结构体成员

如果要访问结构体成员,需要使用点号 . 操作符。

package main

import "fmt"

//定义结构体

type Books struct {

title string

author string

subject string

bookId int

}

func main() {

/* book 1 描述 */

Book1.title = "Go 语言"

Book1.author = "mr.white"

Book1.subject = "Go 语言教程"

Book1.bookId = 100001

/* book 2 描述 */

Book2.title = "Python 教程"

Book2.author = "mr.white"

Book2.subject = "Python 语言教程"

Book2.bookId = 100002

/* 打印 Book1 信息 */

fmt.Printf("Book 1 title : %s\n", Book1.title)

fmt.Printf("Book 1 author : %s\n", Book1.author)

fmt.Printf("Book 1 subject : %s\n", Book1.subject)

fmt.Printf("Book 1 book_id : %d\n", Book1.bookId)

/* 打印 Book2 信息 */

fmt.Printf("Book 2 title : %s\n", Book2.title)

fmt.Printf("Book 2 author : %s\n", Book2.author)

fmt.Printf("Book 2 subject : %s\n", Book2.subject)

fmt.Printf("Book 2 book_id : %d\n", Book2.bookId)

}

查看运行结果:

3.结构体作为函数参数(进阶ToDo)

4.结构体指针(进阶ToDo)

十三、切片

1.定义/切片初始化

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

package main

import "fmt"

func main() {

//1.直接初始化切片,[] 表示是切片类型,{1,2,3} 初始化值依次是 1,2,3,其 cap=len=3。

s := []int{1, 2, 3}

fmt.Println("切片s:", s)

//初始化切片 s1,是数组 s 的引用。

s1 := s[:]

fmt.Println("切片s1:", s1)

//初始化切片 s2,是从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片。

s2 := s[1:3]

fmt.Println("切片s2:", s2)

//使用make初始化切片

s3 := make([]int, 3)

fmt.Println("切片s3:", s3)

}

查看运行结果:

2.len() 和 cap() 函数

len() 方法获取切片的长度

cap()方法 可以测量切片最长可以达到多少

package main

import "fmt"

func printSlice(x []int) {

fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)

}

func main() {

//2调用printSlice方法获取切片的长度与容量

var numbers = make([]int, 3, 5)

printSlice(numbers)

}

查看运行结果:

3.空(nil)切片

package main

import "fmt"

func printSlice(x []int) {

fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)

}

func main() {

//3.空切片

var numbers []int

printSlice(numbers)

if numbers == nil {

fmt.Println("切片是空的呢")

}

}

查看运行结果:

6.切片截取

可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound],实例如下:

package main

import "fmt"

func printSlice(x []int) {

fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)

}

func main() {

//切片截取举例

/* 创建切片 */

numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}

printSlice(numbers)

/* 打印原始切片 */

fmt.Println("numbers ==", numbers)

/* 打印子切片从索引1(包含) 到索引4(不包含)*/

fmt.Println("numbers[1:4] ==", numbers[1:4])

/* 默认下限为 0*/

fmt.Println("numbers[:3] ==", numbers[:3])

/* 默认上限为 len(s)*/

fmt.Println("numbers[4:] ==", numbers[4:])

numbers1 := make([]int, 0, 5)

printSlice(numbers1)

/* 打印子切片从索引 0(包含) 到索引 2(不包含) */

number2 := numbers[:2]

printSlice(number2)

/* 打印子切片从索引 2(包含) 到索引 5(不包含) */

number3 := numbers[2:5]

printSlice(number3)

}

查看运行结果:

7.append() 和 copy() 函数

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。

package main

import "fmt"

func printSlice(x []int) {

fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)

}

func main() {

//5.append() 和 copy() 函数

var numbers []int

printSlice(numbers)

/* 允许追加空切片 */

numbers = append(numbers, 0)

printSlice(numbers)

/* 向切片添加一个元素 */

numbers = append(numbers, 1)

printSlice(numbers)

/* 同时添加多个元素 */

numbers = append(numbers, 2,3,4)

printSlice(numbers)

/* 创建切片 numbers1 是之前切片的两倍容量*/

numbers1 := make([]int, len(numbers), (cap(numbers))*2)

/* 拷贝 numbers 的内容到 numbers1 */

copy(numbers1,numbers)

printSlice(numbers1)

}

查看运行结果:

十四、范围(Range)

1.range的最用

range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环

2.举例说明

package main

import "fmt"

func main() {

map1 := make(map[int]float32)

map1[1] = 1.0

map1[2] = 2.0

map1[3] = 3.0

map1[4] = 4.0

// 读取 key 和 value

for key, value := range map1 {

fmt.Printf("key is: %d - value is: %f\n", key, value)

}

// 读取 key

for key := range map1 {

fmt.Printf("key is: %d\n", key)

}

// 读取 value

for _, value := range map1 {

fmt.Printf("value is: %f\n", value)

}

}

查看运行结果:

十五、集合

1.定义 Map

/* 声明变量,默认 map 是 nil */

var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */

map_variable := make(map[key_data_type]value_data_type)

实例如下:

package main

import "fmt"

func main() {

var countryCapitalMap map[string]string /*创建集合 */

countryCapitalMap = make(map[string]string)

/* map插入key - value对,各个国家对应的首都 */

countryCapitalMap["France"] = "巴黎"

countryCapitalMap["Italy"] = "罗马"

countryCapitalMap["Japan"] = "东京"

countryCapitalMap["India "] = "新德里"

/*使用键输出地图值 */

for country := range countryCapitalMap {

fmt.Println(country, "首都是", countryCapitalMap[country])

}

/*查看元素在集合中是否存在 */

capital, ok := countryCapitalMap["American"] /*如果确定是真实的,则存在,否则不存在 */

/*fmt.Println(capital) */

/*fmt.Println(ok) */

if ok {

fmt.Println("American 的首都是", capital)

} else {

fmt.Println("American 的首都不存在")

}

}

查看运行结果:

2.delete() 函数

delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。实例如下:

package main

import "fmt"

func main() {

//2.delete() 函数

/* 创建map */

countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}

fmt.Println("原始地图")

/* 打印地图 */

for country := range countryCapitalMap {

fmt.Println(country, "首都是", countryCapitalMap[country])

}

/*删除元素*/

delete(countryCapitalMap, "France")

fmt.Println("法国条目被删除")

fmt.Println("删除元素后地图")

/*打印地图*/

for country := range countryCapitalMap {

fmt.Println(country, "首都是", countryCapitalMap[country])

}

}

查看运行结果:

十六、递归

Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。

递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等

1.阶乘

package main

import "fmt"

func Factorial(n uint64) (result uint64) {

if n > 0 {

result = n * Factorial(n-1)

return result

}

return 1

}

func main() {

//1.阶乘

var i int = 15

fmt.Printf("%d 的阶乘是 %d\n", i, Factorial(uint64(i)))

}

查看运行结果:

2.斐波那契数列

package main

import "fmt"

func fibonacci(n int) int {

if n < 2 {

return n

}

return fibonacci(n-2) + fibonacci(n-1)

}

func main() {

//2.斐波那契数列

var i int

for i = 0; i < 10; i++ {

fmt.Printf("%d\t", fibonacci(i))

}

}

查看运行结果:

十七、数据类型转换

1.转换规则

类型转换用于将一种数据类型的变量转换为另外一种类型的变量。Go 语言类型转换基本格式如下:

type_name(expression)

2.实例

package main

import "fmt"

func main() {

var sum int = 17

var count int = 5

var mean float32

mean = float32(sum)/float32(count)

fmt.Printf("mean 的值为: %f\n",mean)

}

查看运行结果:

十八、接口

1.接口含义

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

2.实例

package main

import "fmt"

type Phone interface {

/* 定义结构体 */

call()

}

type NokiaPhone struct {

/* 定义结构体 */

}

func (nokiaPhone NokiaPhone) call() {

/* 实现接口方法 */

fmt.Println("I am Nokia, I can call you!")

}

type IPhone struct {

/* 定义结构体 */

}

func (iPhone IPhone) call() {

/* 实现接口方法 */

fmt.Println("I am iPhone, I can call you!")

}

func main() {

var phone Phone

phone = new(NokiaPhone)

phone.call()

phone = new(IPhone)

phone.call()

}

查看运行结果:

十九、错误处理

1.error简介

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

type error interface {

Error() string}

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) {

if f < 0 {

return 0, errors.New("math: square root of negative number")

}

// 实现}

在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:

result, err:= Sqrt(-1)

if err != nil {

fmt.Println(err)

}

2.实例

package main

import "fmt"

// 定义一个 DivideError 结构

type DivideError struct {

dividee int

divider int

}

// 实现 `error` 接口

func (de *DivideError) Error() string {

strFormat := `

Cannot proceed, the divider is zero.

dividee: %d

divider: 0

`

return fmt.Sprintf(strFormat, de.dividee)

}

// 定义 `int` 类型除法运算的函数

func Divide(varDividee int, varDivider int) (result int, errorMsg string) {

if varDivider == 0 {

dData := DivideError{

dividee: varDividee,

divider: varDivider,

}

errorMsg = dData.Error()

return

} else {

return varDividee / varDivider, ""

}

}

func main() {

// 正常情况

if result, errorMsg := Divide(100, 10); errorMsg == "" {

fmt.Println("100/10 = ", result)

}

// 当除数为零的时候会返回错误信息

if _, errorMsg := Divide(100, 0); errorMsg != "" {

fmt.Println("errorMsg is: ", errorMsg)

}

}

查看运行结果:

二十、并发

1.并发介绍

Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

语句:go f(x, y, z)

如:开启一个新的 goroutine:

f(x, y, z)

2.实例

package main

import (

"fmt"

"time"

)

func say(s string) {

for i := 0; i < 5; i++ {

time.Sleep(100 * time.Millisecond)

fmt.Println(s)

}

}

func main() {

go say("world")

say("hello")

}

查看运行结果;

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章